[LeetCode] 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,
Given the following words in dictionary,
[ "wrt", "wrf", "er", "ett", "rftt" ]
The correct order is:
"wertf"
.
Example 2:
Given the following words in dictionary,
Given the following words in dictionary,
[ "z", "x" ]
The correct order is:
"zx"
.
Example 3:
Given the following words in dictionary,
Given the following words in dictionary,
[ "z", "x", "z" ]
The order is invalid, so return
""
.
Note:
- You may assume all letters are in lowercase.
- You may assume that if a is a prefix of b, then a must appear before b in the given dictionary.
- If the order is invalid, return an empty string.
- There may be multiple valid order of letters, return any one of them is fine.
Thought process:
Topological sort:
- Build graph:
- a map of character -> set of character.
- Also get in-degrees for each character. In-degrees will be a map of character -> integer.
- Topological sort:
- Loop through in-degrees. Offer the characters with in-degree of 0 to queue.
- While queue is not empty:
- Poll from queue. Append to character to result string.
- Decrease the in-degree of polled character's children by 1.
- If any child's in-degree decreases to 0, offer it to queue.
- At last, if result string's length is less than the number of vertices, that means there is a cycle in my graph. The order is invalid.
Solution:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | class Solution { public String alienOrder(String[] words) { Map<Character, Set<Character>> graph = new HashMap<>(); int[] inDegree = new int[26]; buildGraph(words, graph, inDegree); String order = topologicalSort(graph, inDegree); return order.length() == graph.size() ? order : ""; } private void buildGraph(String[] words, Map<Character, Set<Character>> graph, int[] inDegree) { for (String word : words) { for (char c : word.toCharArray()) { graph.put(c, new HashSet<>()); } } for (int i = 1; i < words.length; i++) { String first = words[i - 1]; String second = words[i]; int length = Math.min(first.length(), second.length()); for (int j = 0; j < length; j++) { char parent = first.charAt(j); char child = second.charAt(j); if (parent != child) { if (!graph.get(parent).contains(child)) { graph.get(parent).add(child); inDegree[child - 'a']++; } break; } } } } private String topologicalSort(Map<Character, Set<Character>> graph, int[] inDegree) { Queue<Character> queue = new LinkedList<>(); for (char c : graph.keySet()) { if (inDegree[c - 'a'] == 0) { queue.offer(c); } } StringBuilder sb = new StringBuilder(); while (!queue.isEmpty()) { char c = queue.poll(); sb.append(c); for (char neighbor : graph.get(c)) { inDegree[neighbor - 'a']--; if (inDegree[neighbor - 'a'] == 0) { queue.offer(neighbor); } } } return sb.toString(); } } |
Time complexity:
Say the number of characters in the dictionary (including duplicates) is n. Building the graph takes O(n). Topological sort takes O(V + E). V <= n. E also can't be larger than n. So the overall time complexity is O(n).
Say the number of characters in the dictionary (including duplicates) is n. Building the graph takes O(n). Topological sort takes O(V + E). V <= n. E also can't be larger than n. So the overall time complexity is O(n).
['eff', 'fg'] expected: efg, output: fg
ReplyDelete['eff', 'fg'] expected: efg, output: egf
DeleteQueing all with 0 first.
both "efg" and "egf" and "gef" are correct order.
Deleteonly condition is f should come after e.
This comment has been removed by the author.
ReplyDeleteWhat about ["wrt","wrf","er","ett","rftt","te"] ?? The answer is "wertf"
ReplyDelete["abc","ab"]. This gives a wrong output for the above code
ReplyDeleteExpected: ""
Output: "abc"
one more check is required in this code.
Deletewhile creating graph , if the previous word length is more than the current word.
and current word occurrence is there in previous word then return "";
in C++ it can be done like this :
if(
words[i-1].length() > words[i].length()
and
std::string::npos != words[i-1].rfind( words[i] , 0)
)
That's not in lexicographically order
Delete'abc', 'ab' is not a valid input as per Leetcode Notes
Delete"You may assume that if a is a prefix of b, then a must appear before b in the given dictionary."
see the "Notes" at https://leetcode.ca/all/269.html
Your code doesn't account for the last constraint in the description:
ReplyDelete> 4. There may be multiple valid order of letters, return the smallest in normal lexicographical order
["zb","za"]
Output
"bza"
Expected
"baz"
You need to keep track of the total alphabet vs connected alphabet, i.e. insert all of the disjoint vertices on top of your top-sorted connected vertices according to the lexicographic order.
^
ReplyDeletenvm, looks like the problem was updated. previously, that wasn't the case:
> 4. There may be multiple valid order of letters, return any one of them is fine.
this solution is wrong for ["abcd","ab"]
ReplyDeleteanswer should be empty string but giving "abcd"
your input is not correct as per leetcode guidelines
Delete"You may assume that if a is a prefix of b, then a must appear before b in the given dictionary."
see the "Notes" at https://leetcode.ca/all/269.html
can you explain what the lexicographical order is?
ReplyDeleteMlabialpa-2000 Nicholas Patel https://marketplace.visualstudio.com/items?itemName=neolacpol-ke.Descargar-Wonder-Boy--Asha-In-Monster-World-gratuita-2021
ReplyDeleterifftuconfimb