Given two words, beginWord and endWord, and a dictionary wordList, return the number of words in the shortest transformation sequence from beginWord to endWord, or 0 if no such sequence exists. Every adjacent pair of words differs by a single letter.
Example 1
Input: beginWord = hit, endWord = cog, wordList = ["hot","dot","dog","lot","log","cog"]
Output: 5
Explanation: One shortest sequence is hit → hot → dot → dog → cog. Each step changes one letter, and the sequence contains 5 words.
Example 2
Input: beginWord = hit, endWord = cog, wordList = ["hot","dot","dog","lot","log"]
Output: 0
Explanation: "cog" is not in the word list, so the end word can never be reached. The answer is 0.
Example 3
Input: beginWord = a, endWord = c, wordList = ["a","b","c"]
Output: 2
Explanation: "a" can change directly into "c", so the sequence is a → c, which has 2 words.
Two words are *neighbours* (one-letter apart) iff they match if you mask out one position with `*`. So we precompute, for every word and every position, the pattern that results from masking that position — and bucket all words by their patterns. Now finding all neighbours of a word costs `O(M)` lookups, not `O(N)` scans. BFS finds shortest paths, so the first time we reach `endWord` gives the minimum ladder length.
Run checks all cases above. Submit evaluates all test cases.