# LeetCode – Word Ladder II (Java)

Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from start to end, such that: 1) Only one letter can be changed at a time, 2) Each intermediate word must exist in the dictionary.

For example, given: start = "hit", end = "cog", and dict = ["hot","dot","dog","lot","log"], return:

```  [
["hit","hot","dot","dog","cog"],
["hit","hot","lot","log","cog"]
]
```

Java Solution

This is an extension of Word Ladder. The idea is the same. To track the actual ladder, we need to add a pointer that points to the previous node in the WordNode class. In addition, the used word can not directly removed from the dictionary. The used word is only removed when steps change.

```class Solution {   public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) { List<List<String>> result = new ArrayList<List<String>>();   HashSet<String> unvisited = new HashSet<>(); unvisited.addAll(wordList);   LinkedList<Node> queue = new LinkedList<>(); Node node = new Node(beginWord,0,null); queue.offer(node);   int minLen = Integer.MAX_VALUE; while(!queue.isEmpty()){ Node top = queue.poll();   //top if have shorter result already if(result.size()>0 && top.depth>minLen){ return result; }   for(int i=0; i<top.word.length(); i++){ char c = top.word.charAt(i); char[] arr = top.word.toCharArray(); for(char j='z'; j>='a'; j--){ if(j==c){ continue; } arr[i]=j; String t = new String(arr);   if(t.equals(endWord)){ //add to result List<String> aResult = new ArrayList<>(); aResult.add(endWord); Node p = top; while(p!=null){ aResult.add(p.word); p = p.prev; }   Collections.reverse(aResult); result.add(aResult);   //stop if get shorter result if(top.depth<=minLen){ minLen=top.depth; }else{ return result; } }   if(unvisited.contains(t)){ Node n=new Node(t,top.depth+1,top); queue.offer(n); unvisited.remove(t); } } } }   return result; } }   class Node{ public String word; public int depth; public Node prev;   public Node(String word, int depth, Node prev){ this.word=word; this.depth=depth; this.prev=prev; } }```
Category >> Algorithms >> Interview
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>
```
• Sungil Hong

Wow. Wrong solution. Must be careful.

• Mayank Rathore

@disqus_ge9RooCt3l:disqus You should try yourself rather than googling for solution, Use your mind

• Akhil Mittal

What is the point of a solution which is getting failed for so many inputs?

• Akhil Mittal

Also failing for:
“red”
“tax”
Output:
Expected:

• Akhil Mittal

Fails for the input:

“hit”
“cog”
[“hot”,”dot”,”dog”,”lot”,”log”]

Expected Output is: []

• ryanlr

True, solution is updated.

• Rishi Shah

This code will remove all the previous steps words.
``` if(preNumSteps < currNumSteps){ unvisited.removeAll(visited); } ```

We need to keep that word in the dict. We can’t remove that word as soon as we used it for the first time. Consider this case [“hit”,”hot”,”dot”,”dog”,”cog”], [“hit”,”hot”,”lot”,”log”,”cog”]. “hot” will come twice. If we will remove this we will unable to fetch the second case. In the previous question we only need length of sequence not the all the possible sequences of the shortest length. That’s why the author of this code is not deleting the repeated words as soon as it occurred.

• maninblack2013

I think this program will continue to search until all the words in the dict are removed, which is a huge performance issue. You need to terminate the search after you found all the shortest paths

• Digvijay Singh Rawat

Ok. I got the mistake I was making. Instead of doing top.numstep+1, I was doing ++top.numstep which was increasing step for even same step nodes and thus deleting each visited node on comparing prevstep < currstep.

• Digvijay Singh Rawat

Yes. Even I am getting only one path. Queue is becoming empty between the final loop.

• Jayam

the MinStep & top steps including If conditions are not necessary. I have removed them & all test cases passed.

———————————————————————————————————————-
public static List<List> wordLadderII(String start, String end, List wordList) {
Set dict = new HashSet(wordList);
List<List> paths = new ArrayList();
if (!dict.contains(end)) return paths; // if end not in dict then return

queue.add(new WNode(start, 1, null));// start que with start word & dist as 1

HashSet visited = new HashSet();
HashSet unvisited = new HashSet();
int preDist = 0;

while (!queue.isEmpty()) {
WNode trav = queue.remove();
String word = trav.word;
int currDist = trav.dist;

// type this after you have typed the word forming logic
if (word.equals(end)) { // we ahve found
ArrayList list = new ArrayList();
while (trav.prev != null) {
trav = trav.prev;
}
continue;
}

if (preDist < currDist) { // means we have reached here with the min dist thus there is no point in processsing these words again
unvisited.removeAll(visited);
}
preDist = currDist;

// new word forming logic
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 formed = new String(arr);
if (unvisited.contains(formed)) {
queue.add(new WNode(formed, trav.dist + 1, trav));
}
arr[i] = temp;
}
}
}
return paths;
}
———————————————————————————————————————-

• Kunal Veera

``` import java.util.*; public class HelloWorld{ static ArrayList Dict = new ArrayList(); static String start = "hit"; static String end = "cog"; static ArrayList<ArrayList> ans = new ArrayList(); public static void main(String []args){ ArrayList ch = new ArrayList(); Dict.add("hot"); Dict.add("dot"); Dict.add("dog"); Dict.add("lot"); Dict.add("log"); findS(start, end, ch); System.out.println(ans); }```

``` public static void findS(String s, String e, ArrayList ch){ char[] sToC = s.toCharArray(); ch.add(s); for(int i=0;i<sToC.length;i++){ char old=sToC[i]; for(char c='a'; c<'z';c++){ sToC[i]=c; if((String.valueOf(sToC)).equals(end)){ ch.add(String.valueOf(sToC)); System.out.println("Done"); ans.add(ch); return; } if(Dict.contains(String.valueOf(sToC))){ if(!ch.contains(String.valueOf(sToC))){ ArrayList newA = copy(ch); System.out.println("Gonna call recurse with " + String.valueOf(sToC)); findS(String.valueOf(sToC),end,newA); } } } sToC[i]=old; } } ```

``` public static ArrayList copy(ArrayList ch){ ArrayList newA = new ArrayList(); for(int i=0;i<ch.size();i++){ newA.add(ch.get(i)); } return newA; } } ```

• Prabhat Meghwal

“BSF” Really :O

• Matias SM

I don’t understand why would you need to keep the words in the dictionary (instead of deleting them right away, like in the previous case). If you reach a word again, it means that the result will be necessarily of a longer distance, so it can’t be in the shortest path. For the case of the end word, a simple validation when removing the word from the dict, will do the trick (or a different approach than having it in the dict).

I believe you should keep processing to get all the shortest path solutions, but filtering should be done at the WordNode level. That is: once you find the shortest distance, you don’t process nodes with greater distance than that. Also, because of the way the “graph” is generated in this case, you know that nodes are queued in increasing distance order, so you can stop processing once the best distance is passed.

• Prakash

No, You are thinking it in with 1 example only .
Code is correct on single Iteration of nested loop it will create all possible Threads for LinkedList.
Each thread will return the different path once word match is found.
Array List will hold all possible path.

• Mohamed Hassan

you must remove used elements to avoid loops

• Billionaire

Why remove used elements from hashset can boost performance? Isn’t that hashset is O(1) time complexity?

• If anyone interested for both BFS and DFS approach for finding Word Ladder: