Lessons
Arrays
- Two Sum Problem with Solution
- Best Time to Buy and Sell Stock
- Array Contains Duplicates
- Product of Array Except Self: Optimized Approach
- Maximum Subarray Problem
- Maximum Product Subarray
- Find Minimum in Rotated Sorted Array
- Search in Rotated Sorted Array
- Container With Most Water
- Verifying an Alien Dictionary
- Next Permutation
- Remove Duplicates from Sorted Array
- Find First and Last Position of Element in Sorted Array
- Trapping Rain Water
- Median of Two Sorted Arrays
Dynamic Programming
- Climbing Stairs Problem
- Coin Change Problem
- Longest Increasing Subsequence
- Longest Common Subsequence (LCS)
- Word Break Problem
- Combination Sum Problem
- House Robber Problem
- Decode Ways Problem
- Unique Paths Problem
- Pascal's Triangle Problem
- Generate Parentheses Problem
- Jump Game with Dynamic Programming and Greedy Algorithms
- Regular Expression Matching
- Race Car Problem
Graph
Word Ladder Algorithm
What Is the Word Ladder Problem?
The Word Ladder problem is a type of graph transformation puzzle. You're given two words: a beginWord
and an endWord
, and a word list (dictionary). Your task is to transform the beginWord
into the endWord
by changing only one letter at a time. Each intermediate word must exist in the word list.
This transformation is known as a word sequence transformation, where every step represents a string mutation. Your goal is to find the shortest possible transformation — and for that, we use search optimization, particularly breadth-first search.
Real-World Problem Explained Simply
Let’s say you’re playing a game where you must turn "hit"
into "cog"
:
You can only change one letter at a time, and each result must be a real word from the dictionary: ["hot", "dot", "dog", "lot", "log", "cog"]
.
So one valid transformation could be:
1
"hit" → "hot" → "dot" → "dog" → "cog"
Each step in this ladder is a string mutation, and our goal is to find the shortest such ladder — that’s where the Word Ladder algorithm helps.
Why Breadth-First Search Works Best
To find the shortest path, we use breadth-first search (BFS). This algorithm explores all possible one-letter changes level by level. As soon as it reaches the target word, it stops — guaranteeing the shortest path.
If you used depth-first search instead, you might end up exploring deep, incorrect paths before finding the shortest one — or not finding it efficiently at all.
Using Hashing Technique for Efficient Lookup
Checking if a word exists in the dictionary again and again can slow things down. That's why we use a hashing technique.
We store the dictionary words in a hash map (in Python, this is a set
) to allow for constant-time lookups. This improves performance drastically and makes the search optimization even better.
Dictionary Mapping and Lexical Adjacency
Instead of comparing each word to all others, we preprocess the dictionary using a smart dictionary mapping approach.
We replace each letter in a word with a *
to form generic patterns. This helps group all lexically adjacent words together. For example:
1 2
"hot" becomes: "*ot", "h*t", "ho*"
We build a map like:
1 2 3
*ot → ["hot", "dot", "lot"] h*t → ["hot"] ho* → ["hot"]
This way, we can look up all neighboring words of "hot" in constant time.
Python Code for Word Ladder (Using Hash Map + BFS)
Here’s a complete working example using all these ideas:
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
from collections import defaultdict, deque def ladderLength(beginWord, endWord, wordList): if endWord not in wordList: return 0 L = len(beginWord) all_combo_dict = defaultdict(list) # Preprocessing: Build dictionary mapping for word in wordList: for i in range(L): pattern = word[:i] + '*' + word[i+1:] all_combo_dict[pattern].append(word) # BFS Initialization queue = deque([(beginWord, 1)]) visited = set([beginWord]) while queue: current_word, level = queue.popleft() for i in range(L): pattern = current_word[:i] + '*' + current_word[i+1:] for neighbor in all_combo_dict[pattern]: if neighbor == endWord: return level + 1 if neighbor not in visited: visited.add(neighbor) queue.append((neighbor, level + 1)) # Optional: Clear the list to prevent re-checking all_combo_dict[pattern] = [] return 0
Step-by-Step Explanation of the Code
1. Hash Map Creation
We create a dictionary where each pattern (*ot
, h*t
, etc.) points to a list of words. This allows efficient lookup of all lexical adjacency possibilities.
2. Breadth-First Search
We use a queue to explore transformations level by level. Each queue entry keeps track of the word and its level (or transformation depth).
3. Visited Set
To avoid cycles and redundant checks, we store all visited words in a set.
4. End Condition
The moment we find the endWord
, we return the level — because BFS guarantees it’s the shortest path.
Final Thoughts
The Word Ladder algorithm is a powerful example of how concepts like:
- graph transformation
- breadth-first search
- dictionary mapping
- hashing technique
- and search optimization
…can work together to solve real problems efficiently.
By breaking down the logic and using a hash map for efficient lookup, we make sure the solution is not only correct but also scalable.