[LeetCode] 269. Alien Dictionary
There is a new alien language that uses the English alphabet. However, the order among the letters is unknown to you.
You are given a list of strings words
from the alien language's dictionary, where the strings in words
are sorted lexicographically by the rules of this new language.
Return a string of the unique letters in the new alien language sorted in lexicographically increasing order by the new language's rules. If there is no solution, return ""
. If there are multiple solutions, return any of them.
Example 1:
Input: words = ["wrt","wrf","er","ett","rftt"] Output: "wertf"
Example 2:
Input: words = ["z","x"] Output: "zx"
Example 3:
Input: words = ["z","x","z"]
Output: ""
Explanation: The order is invalid, so return ""
Constraints:
1 <= words.length <= 100
1 <= words[i].length <= 100
words[i]
consists of only lowercase English letters.
火星词典。
现有一种使用字母的全新语言,这门语言的字母顺序与英语顺序不同。
假设,您并不知道其中字母之间的先后顺序。但是,会收到词典中获得一个 不为空的 单词列表。因为是从词典中获得的,所以该单词列表内的单词已经 按这门新语言的字母顺序进行了排序。
您需要根据这个输入的列表,还原出此语言中已知的字母顺序。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/alien-dictionary
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路是拓扑排序,我这里给出的是BFS的解法。首先给每个牵涉到的字母都分别给一个入度1,同时需要计算这里一共牵涉到多少个不同的字母count。之后再次遍历input,这一次需要创建graph的边。创建的方式是用hashmap,分如下几个比较细节的步骤。
单词两两比较,发现第一个不同的字母之后,比如这个例子,
"wrt"和"wrf"
就把t当做key放入hashmap,map的value是一个hashset,再把f加入这个hashset,同时也把f的入度++,之后立即break(因为每两个单词之间其实只能最多得到两个字母之间的相对顺序)。照此遍历完所有的单词之后,根据入度表创建graph,还是把入度为1的字母加入queue。创建了graph之后,再来就是跟course schedule一样用BFS遍历每一条边,弹出queue的那一刻就将遍历到的字符append到结果集中;同时看这个字符是否在hashmap中,若在,也要去查看他对应的hashset里面有没有入度为1的字母,若有也要加入queue。最后如果res结果集的长度跟count不一致则返回空字符串。
时间O(V + E)
空间O(n) - 单词个数
Java实现
1 class Solution { 2 public static String alienOrder(String[] words) { 3 // corner case 4 if (words == null || words.length == 0) { 5 return ""; 6 } 7 8 // normal case 9 StringBuilder res = new StringBuilder(); 10 // 记录字典序 11 HashMap<Character, HashSet<Character>> map = new HashMap<>(); 12 int[] degree = new int[26]; 13 // 记录涉及到的字母的个数,最终输出的字典序的长度 == count 14 int count = 0; 15 for (String word : words) { 16 for (char c : word.toCharArray()) { 17 if (degree[c - 'a'] == 0) { 18 count++; 19 degree[c - 'a'] = 1; 20 } 21 } 22 } 23 24 // 两两单词比较字母的不同 25 for (int i = 0; i < words.length - 1; i++) { 26 char[] cur = words[i].toCharArray(); 27 char[] next = words[i + 1].toCharArray(); 28 // corner case, 会有非法情况 29 // 如果某个单词出现在他的前缀之前,则说明这个排序是不合法的 30 // ["abc", "ab"] 31 if (cur.length > next.length && words[i].startsWith(words[i + 1])) { 32 return ""; 33 } 34 35 // normal case, created the graph 36 int len = Math.min(cur.length, next.length); 37 for (int j = 0; j < len; j++) { 38 if (cur[j] != next[j]) { 39 if (!map.containsKey(cur[j])) { 40 map.put(cur[j], new HashSet<>()); 41 } 42 if (map.get(cur[j]).add(next[j])) { 43 degree[next[j] - 'a']++; 44 } 45 break; 46 } 47 } 48 } 49 50 Queue<Character> queue = new LinkedList<>(); 51 for (int i = 0; i < 26; i++) { 52 if (degree[i] == 1) { 53 queue.offer((char) ('a' + i)); 54 } 55 } 56 57 while (!queue.isEmpty()) { 58 char cur = queue.poll(); 59 res.append(cur); 60 if (map.containsKey(cur)) { 61 for (char next : map.get(cur)) { 62 if (--degree[next - 'a'] == 1) { 63 queue.offer(next); 64 } 65 } 66 } 67 } 68 return res.length() == count ? res.toString() : ""; 69 } 70 }
相关题目