269. Alien Dictionary


June-27-2019

比较难= = 用indegree的思路来做的,或者说拓扑的思路topological sort

prevStr和tempStr,说明prevStr里的char在tempStr里的char之前.
eg: abc&abd => d -> c 说明D前面有一个C

要给所有出现的char建SET,记录前面有哪些char。 SET的大小代表char的indegree是几(前面有几个CHAR)
上面的例子就这样 =>
d : {c}

遍历所有STR来比较,然后从indegree=0的开始删,和course schedule一个做法

有问题的话会出现a的 set里有B, B的SET里有A,相互矛盾。

有个隐藏条件
"abc"
"ab"
是错的,空的永远排在任何字母之前,不容易想到,不用过分纠结这个。

Time Complexity主要耗在遍历上 O(mn)

    public String alienOrder(String[] words) {
        
        Map<Character, Set<Character>> parentMap = new HashMap<>();
        
        for (String s : words) {
            for (char c : s.toCharArray()) {
                if (!parentMap.containsKey(c)) {
                    parentMap.put(c, new HashSet<>());
                }
            }
        }
        
        for (int i = 1; i < words.length; i ++) {
            String prevStr = words[i - 1];
            String tempStr = words[i];
            
            int len = Math.min(prevStr.length(), tempStr.length());
            for (int j = 0; j < len; j ++) {
                char prevChar = prevStr.charAt(j);
                char tempChar = tempStr.charAt(j);
                
                if (prevChar != tempChar) {                                     
                    if (!parentMap.get(tempChar).contains(prevChar)) {
                        parentMap.get(tempChar).add(prevChar);
                    }
                    break;
                }
                if (j == prevStr.length() - 1 && len + 1 == prevStr.length()) return "";
            }
            
        }
        
        ArrayDeque<Character> q = new ArrayDeque<>();
        for (Map.Entry<Character, Set<Character>> entry : parentMap.entrySet()) {
            if (entry.getValue().isEmpty()) {
                q.offerLast(entry.getKey());
            }
        }
        
        StringBuilder sb = new StringBuilder();
        
        while (!q.isEmpty()) {
            char tempChar = q.pollFirst();
            parentMap.remove(tempChar);
            sb.append(tempChar);
            for (Map.Entry<Character, Set<Character>> entry : parentMap.entrySet()) {
                if (entry.getValue().contains(tempChar)) {
                    entry.getValue().remove(tempChar);
                    if (entry.getValue().isEmpty()) {
                        q.offerLast(entry.getKey());
                    }
                }
            }
        }
        
        if (parentMap.isEmpty()) {
            return sb.toString();
        } else {
            return "";
        }
        
    }

=====================
一刷。

直接看的解法,大多数是用拓扑排序做的。

说实话挺难的,直接看别人的CODE才理解。

一开始也理解错了,单词里面的letter是没有顺序的,只是dictionary是按特殊顺序排列的。但是又不能只比较首字母,因为有可能首字母相同。

Time: 假如26个字母。 不是很好算。。

建图最差是N*N,但是这种情况发生时,整个图都是V,没有E。 就不用后面的拓扑排序了。拓扑排序是有边,才可以。。
O(26²) + O(26) + O(26) * O(E) 大概这么个意思
第一个26平方是建图,然后O(26)是入queue, O(26) * O(E)是拓扑排序。。

这个题还有别的坑。

"abc"
"abcd"
这样是没事的

"abcd"
"abc"
这样是错的,‘ ’在‘d'之前是错的。
有个rule没说,' ' shall before any letters,但是大家基本都以为Alien rule can be any rules it defines..= =

public class Solution {
    public String alienOrder(String[] words) {
        if (words.length == 0) return "";
        
        Set<Character> letterSet = new HashSet<>();
        int[] inDegree = new int[26];
        Map<Character, HashSet<Character>> order = new HashMap<>();
        
        for (String s : words) {
            for (char c : s.toCharArray()) {
                letterSet.add(c);
            }
        }

        for (int i = 1; i < words.length; i++) {
            String prevStr = words[i-1];
            String tempStr = words[i];
            
            if (prevStr.equals(tempStr)) continue;
            
            int len = Math.min(prevStr.length(), tempStr.length());
            
            for (int j = 0; j < len; j++) {
                char prevC = prevStr.charAt(j);
                char tempC = tempStr.charAt(j);
                if (prevC != tempC) {
                    if (!order.containsKey(prevC)) {
                        order.put(prevC, new HashSet<>());
                    }
                    
                    if (!order.get(prevC).contains(tempC)) {
                        order.get(prevC).add(tempC);
                        inDegree[tempC - 'a'] ++;
                    }
                    break;
                }
                if (j == len - 1 && prevStr.length() > tempStr.length()) return "";
            }
        }
       
        
        Queue<Character> q = new LinkedList<>();
        for (int i = 0; i < inDegree.length; i++) {
            if (inDegree[i] == 0 && letterSet.contains((char)('a' + i))) {
                q.offer((char)('a' + i));
            }
        }
        
        StringBuilder sb = new StringBuilder();
        while (!q.isEmpty()) {
            char tempChar = q.poll();
            sb.append(tempChar);
            if (order.containsKey(tempChar)) {
                for (char c : order.get(tempChar)) {
                    inDegree[c - 'a'] --;
                    if (inDegree[c - 'a'] == 0) {
                        q.offer(c);
                    }
                }
            }
        }
        
        if (sb.length() != letterSet.size()) {
            return "";
        } else {
            return sb.toString();
        }
    }
}
posted @ 2016-12-11 01:14  哇呀呀..生气啦~  阅读(384)  评论(0编辑  收藏  举报