Given two words (start and end), and a dictionary, find the length of shortest transformation sequence from start to end, such that only one letter can be changed at a time and each intermediate word must exist in the dictionary. For example, given:

```start = "hit"
end = "cog"
dict = ["hot","dot","dog","lot","log"]
```

One shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog", the program should return its length 5.

Java Solution

This is a search problem, and breath-first search guarantees the optimal solution.

```class WordNode{ String word; int numSteps;   public WordNode(String word, int numSteps){ this.word = word; this.numSteps = numSteps; } }   public class Solution { public int ladderLength(String beginWord, String endWord, Set<String> wordDict) { LinkedList<WordNode> queue = new LinkedList<WordNode>(); queue.add(new WordNode(beginWord, 1));   wordDict.add(endWord);   while(!queue.isEmpty()){ WordNode top = queue.remove(); String word = top.word;   if(word.equals(endWord)){ return top.numSteps; }   char[] arr = word.toCharArray(); for(int i=0; i<arr.length; i++){ for(char c='a'; c<='z'; c++){ char temp = arr[i]; if(arr[i]!=c){ arr[i]=c; }   String newWord = new String(arr); if(wordDict.contains(newWord)){ queue.add(new WordNode(newWord, top.numSteps+1)); wordDict.remove(newWord); }   arr[i]=temp; } } }   return 0; } }```
Category >> Algorithms
If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
```<pre><code>
String foo = "bar";
</code></pre>
```
• SM TechWorld

Simple Java Solution With Step By Step Explanation .

https://youtu.be/rMveRF-BYac

• Alik Elzin

So my thought, if the dictionary isn’t that big, provide all options of the dictionary words with one letter missing.
This way, we can find the matching “1-letter changed” quickly – without traversing through all the abc.
Such a dictionary from the example would be:
[-ot, h-t, ho-, -ot, d-t, do-, -og, d-g, do-, -ot, l-t, lo-, -og, l-g, lo-].
We still need to save the original word so we’ll add it to the dictionary.
If we have the space, and can partition the dictionary based on string length, the iteration over the abc would be faster – O(size-of-word) instead of O(abc…z)=O(26).

What do you think?

• Alik Elzin

So the solution I see iterates over all the “abc…z” – for each letter in each word in the queue. On each iteration, the new built word is compared to all dictionary words, using `Set.contains()`.
I was thinking, perhaps it might be faster to compare letter by letter.
But the set, especially if it’s a `HashSet`, will do the contains much faster because of the String’s `hashCode()`.
Just sharing a thought 🙂

• onewithsix

LOL SERIOUSLY 😀

• Aman Gupta

wow, what a catch man!

• Mamed

• Arvind Raj

``` const shortestPath = (start, end, dict, path=[]) => { if (start === end) { return 2 }```

``` ```

``` let results = [] for (var i = 0; i < start.length; i++ ) { for (var j ='a'.charCodeAt(0); j -1 && path.indexOf(next) === -1) { results.push(shortestPath(next, end, dict, path.concat(next)) + 1) } else if (next === end) { return 2 } } } return Math.min(...results) } ```

• Mihai

defining distance between words to be number of letters which are different then we start like this

dequeuing from processing queue
compute distance from item to each in the dictionary O(Dict)
add to queue the ones with distance one and remove them from dict so that you don’t loop

If the dictionary can be prepressed then you can organize it as a graph with arches connecting elements which have dinstance 1.

Then is just a matter of breath-first search and display the result.

You have to check the newWord with the endWord
``` String newWord = new String(arr); if (dict.contains(newWord)) { System.out.println(newWord); queue.add(new WordNode(newWord, top.numSteps + 1)); dict.remove(newWord); // you have to add the next lines. if (newWord.equals(end)) { // System.out.println("equals!"); return top.numSteps; } } ```

• Hoc Ngo

// “hit” -> “cit” -> “cot” -> “cog” => every intermediate word must exist in the dictionary, but “cit” doesn’t.

• Howard Wang

• indiver kumar

I have Solved this problem in my way.Can please anyone locate the use case in which it will break

package com.cpa.examples;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

private static String start = “hit”;
private static String end = “cog”;
private static List Dictionary = null;
private static ArrayList availablePathCntList = new ArrayList();

public static void main(String[] args) {

Dictionary = new ArrayList();

HashSet used = new HashSet();

int count = 0;

find(Dictionary, start, end, used, count);

System.out.println(availablePathCntList);

}

private static int find(List dictionary, String start, String end, HashSet used, int count) {

if (start == end) {
return 0;

}
if (difference(start, end) == 1) {
return 0;
}

for (String word : dictionary) {

int diff = difference(start, word);
if (difference(end, word) == 0) {
continue;
}
if (diff == 0) {
continue;
}
if (diff <= 1 && used.add(word)) {
System.out.println("Your word is: " + start + " and matching word is " + word);

if (diff <= 1) {
if (difference(end, word) == 1) {
} else {
count++;
find(Dictionary, new String(word), new String(end), (HashSet) used.clone(), count);
}

}
}

}
return 0;

}

private static int difference(String first, String second) {

char[] firstArr = first.toCharArray();
char[] secondArr = second.toCharArray();
int mismatch = 0;

for (int i = 0; i < firstArr.length; i++) {

if (firstArr[i] != secondArr[i]) {
mismatch++;
}
}

return mismatch;
}

}

• Bismoy Murasing

I don’t understand why this code is posted, it has time limit exceeded issue on Leetcode.

• lekzeey

This can definitely be better. You should include visited words and make sure you are not adding visited words back to the graph.

• Steve Dyson

any c# code?

• Steve Dyson

this is not working, returns 0

for the same input as yours with dictionary changed to below:

dict = [“hot”,”dot”,”dog”,”lot”,”aog”,”log”]

answer will change like : “hit” -> “hot” -> “dot” -> “dog” -> “aog”->”cog”,

but from dog to cog also we can go directly, how will you avoid that?

• Eugene Arnatovich

Solution just using 2 HashMaps and 1 ArrayList
` `

``` package leetcode; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class Solution { private static int min = Integer.MAX_VALUE; private static List visitedkeys = new ArrayList(); public void wordladder(String start, String end, String[] dict) { //Word ladder Map map2 = new HashMap(); Map<String, List> map = new HashMap(); int i=0; map2.put(i++, start); map.put(start, new ArrayList()); for (String d : dict) { map2.put(i++, d); map.put(d, new ArrayList()); } map2.put(i, end); map.put(end, new ArrayList()); int n = map2.size(); for (i=0; i < n; i++) { for (int j=0; j < n; j++) { if (isConvertible(map2.get(i), map2.get(j))) { map.get(map2.get(i)).add(map2.get(j)); } } } length(map, start, end, 1); if (min != Integer.MAX_VALUE){ System.out.println(min); } else { System.out.println("no path"); } } private boolean isConvertible(String s1, String s2) { if (s1.length() != s2.length()) { return false; } int diff = 0; for (int i = 0; i < s1.length(); i++) { if (s1.charAt(i) != s2.charAt(i)) { diff += 1; } } return (diff == 1) ? true : false; } private void length(Map<String, List> map, String key, String end, int len) { if (key == end) { if (len < min) min = len; return; } List lst = map.get(key); for (String v : lst) { if (!visitedkeys.contains(v)){ visitedkeys.add(v); length(map, v, end, len+1); visitedkeys.remove(visitedkeys.size()-1); } } } } ```

• Dhanaraj D

Does this solution give length of shortest transformation sequence or length of first sequence found ?

• Surbhi Motghare

Can you please tell me the complexity for both the methods?

• subash sethy

can you tell me what is the complexity of this method

• Roman

Solution posted in the task is not correct.

Here is mine:

Test.java file:
``` import java.util.*; public class Test { public static void main(String argv[]){ String start = "hit"; String end = "cog"; String[] dict = {"cot","hot","dot","cit","dog","lot","log"}; // "hit" -> "cit" -> "cot" -> "cog" // length = 4 int minDistance = getDistance(start, end); List nodesToCheck = new ArrayList(); List newNodes = new ArrayList(); List winners = new ArrayList(); nodesToCheck.add(new TreeElem(start, null, minDistance, 1)); do { for (TreeElem node : nodesToCheck) { for (int i = 0; i 0); if (winners.size() == 0) { System.out.println("No solution found."); return; } TreeElem winner = null; int minLength = -1;```

``` for (TreeElem e : winners) { if (winner == null) { winner = e; minLength = e.distanceFromTop; } ```

``` if (e.distanceFromTop = 0; i--) { System.out.print("[" + steps[i] + "] -> "); } System.out.println("[" + end + "]"); } public static int getDistance(String str1, String str2) { int dist = 0; for (int i = 0; i < str1.length(); i++) { if (str1.charAt(i) != str2.charAt(i)) { dist++; } } return dist; } public static boolean isUsed(TreeElem node, String value) { while (node.parent != null) { if (node.value.equals(value)) { return true; } node = node.parent; } return false; } } ```

TreeElem.java file:

``` import java.util.*; public class TreeElem{ public String value; public TreeElem parent; List childs; public int distanceToEnd; public int distanceFromTop; public TreeElem(String value, TreeElem parent, int distanceToEnd, int distanceFromTop) { this.value = value; this.parent = parent; this.childs = new ArrayList(); this.distanceToEnd = distanceToEnd; this.distanceFromTop = distanceFromTop; } public void addChild(TreeElem child) { childs.add(child); } } ```

• CRH

Without using a queue. Please let me know if you see any issues with this?

``` public int getCount(String start, String end, Set dict){ // Basic edge cases if(start==null || end==null || start.length()!=end.length()) return -1; if(dict.isEmpty()) return -1; dict.add(end); int count = 0; int i = 0; while(i<start.length()){ boolean found = false; char[] arr = start.toCharArray(); char tmp = arr[i]; for(int j=97;j<=122;j++){ arr[i] = (char)j; String checker = new String(arr); if(dict.contains(checker)){ count++; dict.remove(checker); if(checker.equals(end)) { return count; } else { start = checker; found = true; i = 0; break; } } } if(!found){ arr[i] = tmp; i++; } } return -1; } ```

• Can be solved by Dijkstra.

• Too much code for an interview or competition problem.
Try to keep it as simple and small as possible 😉

• BFS is a really good way of solving this problem

Hi
I have solved this problem using Graph of word and then run on it BFS.

package Questions;

import java.util.HashMap;
import java.util.Queue;
import java.util.HashSet;

//solution function
public static int ladderLength(String start, String end,
HashSet dict) {
// saving the graph nodes on hash map.
HashMap nodes = new HashMap();
// adding the start and the end words to the dict
for (String word : dict) {
nodes.put(word, new GraphNode(word));
}
// update each node’s adjacents according to one character different relation
Object[] dictArray = dict.toArray();
for (int i = 0; i < dictArray.length; i++) {
for (int j = i + 1; j < dictArray.length; j++) {
if (isNeighbor((String) dictArray[i], (String) dictArray[j])) {
.get((String) dictArray[j]));
.get((String) dictArray[i]));
}
}
}

// Run BFS on the Graph and take the dist generated as result
HashMap result = BFS(nodes, start);

// Return the distance of the end word node from the start word node
return result.get(end);

}

// BFS function
public static HashMap BFS(
HashMap nodes, String start) {

HashMap visited = new HashMap();
HashMap dist = new HashMap();
for (String key : nodes.keySet()) {
visited.put(key, 0);
dist.put(key, 0);
}
visited.put(start, 1);
while (!q.isEmpty()) {
String dequeued = q.remove();
GraphNode curNode = nodes.get(dequeued);
for (int i = 0; i < currAdjs.size(); i++) {
}

}
}
return dist;

}

// check if two words differ by one character
public static boolean isNeighbor(String a, String b) {
assert a.length() == b.length();
int differ = 0;
for (int i = 0; i 1)
return false;
}
return true;
}

public static void main(String[] args) {
// dict = [“hot”,”dot”,”dog”,”lot”,”log”] result 5;
HashSet dict = new HashSet();
}

}

class GraphNode {
String word;

public GraphNode(String word) {
this.word = word;
}
}
I would like to have feedback on my code ?
Thanks

• Stephen Boesch

That’s nice idea to keep only the actual existing letters at each index.

• Stephen Boesch

suboptimal solutions. Better would be 1-grams.

• dwelo

You also don’t necessarily need two queues. You could create a WordNode class inside the method and have a word field and a distance field. Then you can create a queue of “WordNode”s. Also, I think there is no need to compare the distance to previously recorded one, since breadth search will reach the end word in the shortest path. Whenever you reach the end word, that is the shortest distance.

• Nooby

Thanks a ton!! You rock!! Keep it up 🙂

• ryanlr

The problem is fixed.

• ryanlr

Thanks! Changed. And you are welcome:)

• zhuoran

You just need to add end to dict. Then it will be correct.
Btw, thanks a lot for ur code:)

• Curious Guy

You can create a separate list that stores words when found in the dictionary.

• Cong

Yes, you are right. Surprisingly, the seoncd one can be acceptted by leetcode.

• hdante

shortest path problem with dictionary extended to include start and end and weight equals to 1 if distance(a, b) == 1, else weight equals infinite

• BK

we stop at the first time we find the target word and return “length”. All the words that will be added in the stack after that will be > length as we push words in stack after length +1 .

• BK

We can add a condition that if (newword.equals(target)) return currDistance +1;

• dfgd

yeah second algo is wrong

• Guanting

Hi! I think you were oversimplifying the problem. the edge cannot be weighted just based on the number of characters in common. And an edge cannot even be determined between two words just because they have common characters. You have to factor in what are included the dictionary. One simple example, ‘good’ and ‘doom’ have two common characters and suppose the dictionary only contains ‘good’ and ‘doom’…Apparently no edge of path could be established between the two words.

• ryanlr

Why? And how does a correct one look like?

• Shaochen Huang

Agree with most of the comments here:

First: the dictionary here needs to include the end word

Second: the second solution does not find the optimal shortest path, it only finds the first valid path.

I have come up with my own solution which does the following:

1. Instead of trying to iterate through all chars from a to z, it parses the dictionary and maintains a map between index and possible chars for that index in the dictionary, so flipping a character only flipped to possible dictionary words.

2. recursive Graph depth first search which keeps tracks of all sub path size and choose the shortest one.

Please kindly review and comment to help improve the algo

• Yifan Peng

I think this solution is totally wrong.

• Sole

I think there should be a check on the currWord and the end to stop the search in the dict:

``````
/*if(currWord.equals(end)){
return currDistance;
}*/
if(isLastWord(currWord,end)){
break;
}
where isLastWord is something like this:

private boolean isLastWord(String current, String end){
int count = 0;
boolean isLastWord = true;
for(int i=0; i1){
isLastWord = false;
break;
}
}
}
return isLastWord;
}
``````
• AlgorithmFreak

The second solution doesn’t work. Try with input: “hit”, “lag”, [“hot”,”hog”,”dot”,”dog”,”lot”,”log”]
Example sequence: hit > hot > hog > log > lag The answer should be 5. But, it shows 0

• Tex

I mean first

• Tex

Priest solution is obviously wrong even if don’t consider if it’s optimally

• ajay

how it will accepted?? as it will not return as cog is not inside in dict, so currWord.equals(end) will false and return 0.

• hbrong

The algorithm can’t guarantee find the shortest transformation sequence.

• Dun Liu

Nice!!!

• Kae Pajunar

• jason

This should be a shortest path problem: if two words has common character, they are connected by edge. The weight of the edge is the number of character in common. So the problem becomes shortest path problem.

• elvalord