269. Alien Dictionary

本文介绍了一种算法,用于根据给定的按字典序排列的外星语言单词列表来推导该语言中字母的正确排序。通过构建拓扑图并使用广度优先搜索来确定字母间的相对顺序。
There is a new alien language which uses the latin alphabet. However, the order among letters are unknown to you. You receive a list of non-empty words from the dictionary, where words are sorted lexicographically by the rules of this new language. Derive the order of letters in this language.
Example 1:

Given the following words in dictionary,
[
  "wrt",
  "wrf",
  "er",
  "ett",
  "rftt"
]

The correct order is: "wertf".
Example 2:

Given the following words in dictionary,
[
  "z",
  "x"
]

The correct order is: "zx".
Example 3:

Given the following words in dictionary,
[
  "z",
  "x",
  "z"
]

The order is invalid, so return "".
Note:

  1. You may assume all letters are in lowercase.
  2. You may assume that if a is a prefix of b, then a must appear before b in the given dictionary.
  3. If the order is invalid, return an empty string.
  4. There may be multiple valid order of letters, return any one of them is fine.
简单来说 给出的是字典的一部分 按照字典序排序 求字母的排序
比如英文字典中 首先是a开头的字母 然后是b开头的字母 对于同样是a开头的字母 比较后面的字母 哪个字母在在字母表中的位置靠前 那么就在前面
比如 abc在abs之前 前面的ab相同 c在字母表中的位置比s靠前 所以排序是 abc->abs

这是一个排序问题 怎么排序?按照出现的先后排序
比如 
[
  "wrt",
  "wrf",
  "er",
  "ett",
  "rftt"
]
从上到下 w在e之前 e在r之前 所以排序是 w->e->r
然后从左到右 只有两个字母前面的字母相同时才可以比较
比如 wrt和wrf wr之后 t在f之前 所以排序是 t->f

也就是按照当前字母前面出现的字母个数排序 比如w前面有0个字母 e前面有w一个字母 r前面有e一个字母 加上字母e前面有w一个字母
所以 w前面有0个字母 e前面有1个字母 r前面有2个字母 排序是w->e->r

到这里 可以看出本题可以归结为一个拓扑问题 w后面连接了e节点 e后面连接了r节点
首先统计入度 w的入度是0 e的入度是1 r的入度是2
首先统计入度为0的节点 放入结果中 然后取出w后连接的节点 将他们的入度-1 如果有入度为0的节点 再放入结果中
整个过程像是在一个拓扑图中进行广度优先遍历

代码如下

public String alienOrder(String[] words) {
    Map<Character, Set<Character>> map=new HashMap<Character, Set<Character>>();
    Map<Character, Integer> degree=new HashMap<Character, Integer>();
    String result="";
    if(words==null || words.length==0) return result;
    for(String s: words){
        for(char c: s.toCharArray()){
            degree.put(c,0);
        }
    }
    for(int i=0; i<words.length-1; i++){
        String cur=words[i];
        String next=words[i+1];
        int length=Math.min(cur.length(), next.length());
        for(int j=0; j<length; j++){
            char c1=cur.charAt(j);
            char c2=next.charAt(j);
            if(c1!=c2){
                Set<Character> set=new HashSet<Character>();
                if(map.containsKey(c1)) set=map.get(c1);
                if(!set.contains(c2)){
                    set.add(c2);
                    map.put(c1, set);
                    degree.put(c2, degree.get(c2)+1);
                }
                break;
            }
        }
    }
    Queue<Character> q=new LinkedList<Character>();
    for(char c: degree.keySet()){
        if(degree.get(c)==0) q.add(c);
    }
    while(!q.isEmpty()){
        char c=q.remove();
        result+=c;
        if(map.containsKey(c)){
            for(char c2: map.get(c)){
                degree.put(c2,degree.get(c2)-1);
                if(degree.get(c2)==0) q.add(c2);
            }
        }
    }
    if(result.length()!=degree.size()) return "";
    return result;
}


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值