953. Verifying An Alien Dictionary - Explanation

Problem Link

Description

In an alien language, surprisingly, they also use English lowercase letters, but possibly in a different order. The order of the alphabet is some permutation of lowercase letters.

Given a sequence of words written in the alien language, and the order of the alphabets, return true if and only if the given words are sorted lexicographically in this alien language.

Example 1:

Input: words = ["dag","disk","dog"], order = "hlabcdefgijkmnopqrstuvwxyz"

Output: true

Explanation: The first character of the strings are same ('d'). 'a', 'i', 'o' follows the given ordering, which makes the given strings follow the sorted lexicographical order.

Example 2:

Input: words = ["neetcode","neet"], order = "worldabcefghijkmnpqstuvxyz"

Output: false

Explanation: The first 4 characters of both the strings match. But size of "neet" is less than that of "neetcode", so "neet" should come before "neetcode".

Constraints:

  • 1 <= words.length <= 100
  • 1 <= words[i].length <= 20
  • order.length == 26
  • All characters in words[i] and order are English lowercase letters.


Topics

Company Tags

Please upgrade to NeetCode Pro to view company tags.



Prerequisites

Before attempting this problem, you should be comfortable with:

  • Hash Maps - Used to map alien characters to their index positions for O(1) lookups
  • Custom Comparators - Defining custom sorting logic to compare strings based on non-standard ordering
  • String Comparison - Comparing strings character by character, including handling prefix cases

1. Sorting

Intuition

If the words are sorted according to the alien dictionary order, they should remain in the same order after sorting. The key insight is that we can create a mapping from each character to its position in the alien alphabet, then use this mapping to define a custom comparator for sorting.

Algorithm

  1. Create a mapping from each character to its index position in the order string.
  2. Define a comparison function that compares two words character by character using the alien order indices.
  3. For characters that differ, the word with the smaller index character comes first.
  4. If all compared characters are equal, the shorter word comes first.
  5. Sort a copy of the words array using this custom comparator.
  6. Compare the sorted array with the original array and return true if they are identical.
class Solution:
    def isAlienSorted(self, words: List[str], order: str) -> bool:
        order_index = {c: i for i, c in enumerate(order)}

        def compare(word):
            return [order_index[c] for c in word]

        return words == sorted(words, key=compare)

Time & Space Complexity

  • Time complexity: O(nmlogn)O(n * m\log n)
  • Space complexity: O(nm)O(n * m)

Where nn is the number of words and mm is the average length of a word.


2. Comparing adjacent words

Intuition

For a list to be sorted, each adjacent pair must be in the correct order. Instead of sorting, we can directly verify that each word is lexicographically less than or equal to the next word according to the alien order. This avoids the overhead of sorting.

Algorithm

  1. Create a mapping from each character to its index position in the order string.
  2. Iterate through adjacent pairs of words (w1, w2) in the array.
  3. Compare characters at each position until a difference is found or one word ends.
  4. If w1 is longer than w2 and all compared characters match, return false (prefix violation).
  5. If characters differ, check that w1's character has a smaller index than w2's character in alien order. If not, return false.
  6. If all adjacent pairs pass validation, return true.
class Solution:
    def isAlienSorted(self, words: List[str], order: str) -> bool:
        order_index = {c: i for i, c in enumerate(order)}

        for i in range(len(words) - 1):
            w1, w2 = words[i], words[i + 1]

            for j in range(len(w1)):
                if j == len(w2):
                    return False

                if w1[j] != w2[j]:
                    if order_index[w1[j]] > order_index[w2[j]]:
                        return False
                    break
        return True

Time & Space Complexity

  • Time complexity: O(nm)O(n * m)
  • Space complexity: O(1)O(1) since we have 2626 different characters.

Where nn is the number of words and mm is the average length of a word.


Common Pitfalls

Ignoring the Prefix Case

When comparing two words where one is a prefix of the other (e.g., "apple" and "app"), the shorter word must come first. If the longer word appears before its prefix in the list, the order is invalid. Many solutions forget to check this case and only compare differing characters.

Breaking Too Early or Too Late in Character Comparison

When comparing adjacent words character by character, you must break out of the loop as soon as you find the first differing character. Continuing to compare after finding a difference can lead to incorrect conclusions, as only the first difference determines the relative order of two words.