Lesson 157 of 250
953. Verifying an Alien Dictionary
NeetCode: Verifying an Alien Dictionary · LeetCode: 953. Verifying an Alien Dictionary · Difficulty: Easy
Given an array of words written in an alien language and the order of its 26 lowercase letters, return true if the words are sorted lexicographically in that language.
Example
Input: words = ["hello","leetcode"], order = "hlabcdefgijkmnopqrstuvwxyz" Output: true
Input: words = ["word","world","row"], order = "worldabcefghijkmnpqstuvxyz" Output: false
Input: words = ["apple","app"], order = "abcdefghijklmnopqrstuvwxyz" Output: falseTwo words compare by their first differing letter; if one is a prefix of the other, the shorter word comes first.
Brute force: compare every pair of words
Build a rank array mapping each letter to its position in order. A sorted list means every earlier word is <= every later word, so check all pairs i < j. This is quadratic in the number of words.
class Solution {
// True when word a is <= word b in the alien order.
private boolean le(String a, String b, int[] rank) {
int len = Math.min(a.length(), b.length());
for (int i = 0; i < len; i++) {
int x = rank[a.charAt(i) - 'a'];
int y = rank[b.charAt(i) - 'a'];
if (x != y) {
return x < y;
}
}
return a.length() <= b.length();
}
public boolean isAlienSorted(String[] words, String order) {
int[] rank = new int[26];
for (int i = 0; i < order.length(); i++) {
rank[order.charAt(i) - 'a'] = i;
}
for (int i = 0; i < words.length; i++) {
for (int j = i + 1; j < words.length; j++) {
if (!le(words[i], words[j], rank)) {
return false;
}
}
}
return true;
}
}
public class Main {
public static void main(String[] args) {
Solution s = new Solution();
String abc = "abcdefghijklmnopqrstuvwxyz";
System.out.println(s.isAlienSorted(new String[]{"hello", "leetcode"}, "hlabcdefgijkmnopqrstuvwxyz"));
System.out.println(s.isAlienSorted(new String[]{"word", "world", "row"}, "worldabcefghijkmnpqstuvxyz"));
System.out.println(s.isAlienSorted(new String[]{"apple", "app"}, abc));
System.out.println(s.isAlienSorted(new String[]{}, abc));
}
}true
false
false
trueTime: O(k^2 * L) for k words of length up to L. Space: O(1).
Optimal: compare adjacent words only
The order relation is transitive: if w0 <= w1 and w1 <= w2 then w0 <= w2. So it is enough to check each neighbouring pair. Each character is examined at most twice, so the work is linear in the input size.
class Solution {
public boolean isAlienSorted(String[] words, String order) {
int[] rank = new int[26];
for (int i = 0; i < order.length(); i++) {
rank[order.charAt(i) - 'a'] = i;
}
for (int w = 0; w + 1 < words.length; w++) {
String a = words[w];
String b = words[w + 1];
boolean decided = false;
int len = Math.min(a.length(), b.length());
for (int i = 0; i < len; i++) {
int x = rank[a.charAt(i) - 'a'];
int y = rank[b.charAt(i) - 'a'];
if (x != y) {
if (x > y) {
return false;
}
decided = true;
break;
}
}
if (!decided && a.length() > b.length()) {
return false;
}
}
return true;
}
}
public class Main {
public static void main(String[] args) {
Solution s = new Solution();
String abc = "abcdefghijklmnopqrstuvwxyz";
System.out.println(s.isAlienSorted(new String[]{"hello", "leetcode"}, "hlabcdefgijkmnopqrstuvwxyz"));
System.out.println(s.isAlienSorted(new String[]{"word", "world", "row"}, "worldabcefghijkmnpqstuvxyz"));
System.out.println(s.isAlienSorted(new String[]{"apple", "app"}, abc));
System.out.println(s.isAlienSorted(new String[]{}, abc));
}
}true
false
false
trueTime: O(total characters). Space: O(1) (the 26-entry array).
