详细见:leetcode.com/problems/word-ladder-ii
Java Solution: github
package leetcode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
/*
* Given two words (beginWord and endWord), and a dictionary's word list,
* find all shortest transformation sequence(s) from beginWord to endWord, such that:
Only one letter can be changed at a time
Each intermediate word must exist in the word list
For example,
Given:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]
Return
[
["hit","hot","dot","dog","cog"],
["hit","hot","lot","log","cog"]
]
Note:
All words have the same length.
All words contain only lowercase alphabetic characters.
*/
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
/**
* @author zxwtry
* @email zxwtry@qq.com
* @project OJ
* @package leetcode
* @file P126_WordLadderII.java
* @type P126_WordLadderII
* @date 2016年12月13日 下午5:16:11
* @details Solution: AC 204ms 65.85%
*/
public class P126_WordLadderII {
public static void main(String[] args) {
String s = "hit";
String e = "cog";
String[] ss = {"hot","dot","dog","lot","log","cog"};
List<String> w = Arrays.asList(ss);
System.out.println(new Solution().findLadders(s, e, w));
}
static class Solution {
public List<List<String>> findLadders(String s, String t, List<String> w) {
List<List<String>> ans = new LinkedList<List<String>>();
if (s == null || t == null || w == null) {
if (s == null && t == null)
ans.add(Arrays.asList((String)null));
return ans;
}
if (s.equals(t)) {
ans.add(Arrays.asList(s));
return ans;
}
int sn = s.length();
if (w.size() == 0) return ans;
HashSet<String> nv = new HashSet<String>(w);
HashSet<String> hv = new HashSet<String>();
if (! nv.contains(t)) return ans;
nv.add(s);
Queue<String> q = new LinkedList<String>();
q.add(s);
HashMap<String, List<String>> m = new HashMap<String, List<String>>();
char[] cs = new char[sn];
boolean isFind = false;
while (! q.isEmpty()) {
int size = q.size();
while (size -- > 0) {
String n = q.poll();
for (int i = 0; i < sn; i ++) cs[i] = n.charAt(i);
for (int i = 0; i < sn; i ++) {
for (char c = 'a'; c <= 'z'; c ++) {
cs[i] = c;
String nn = new String(cs);
if (! nv.contains(nn)) continue;
if (hv.add(nn)) q.add(nn);
if (! m.containsKey(nn)) m.put(nn, new LinkedList<String>());
m.get(nn).add(n);
if (nn.equals(t)) isFind = true;
}
cs[i] = n.charAt(i);
}
}
if (isFind) break;
nv.removeAll(hv);
hv.clear();
}
System.out.println(m);
find(t, s, new LinkedList<String>(), m, ans);
return ans;
}
private void find(String t, String s, LinkedList<String> l, HashMap<String, List<String>> m,
List<List<String>> ans) {
l.addFirst(t);
if (t.equals(s)) {
ans.add(new LinkedList<String>(l));
} else {
for (String v : m.getOrDefault(t, new ArrayList<String>(0)))
find(v, s, l, m, ans);
}
l.removeFirst();
}
}
}
CPP Solution: github
#pragma warning(disable:4786)
#pragma warning(disable:4503)
/*
url: leetcode.com/problems/word-ladder-ii
too many advanced data structure
use cpp
Solution: AC 259ms 51.41%
*/
#include <iostream>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <string>
using namespace std;
class Solution {
public:
void find(string t, string s, vector<string >& v, map<string, vector<string > >& m, vector<vector<string > >& ans) {
v.insert(v.begin(), t);
if (! t.compare(s)) {
ans.push_back(v);
} else if (m.count(t)) {
for (vector<string >::iterator iter = m[t].begin(); iter != m[t].end(); iter ++)
find(*iter, s, v, m, ans);
}
v.erase(v.begin());
}
vector<vector<string > > findLadders(string s, string t, vector<string>& w) {
vector<vector<string > > ans;
int sn = s.size() , i;
set<string > nv , hv;
for (i = 0; i < w.size(); i ++) nv.insert(w[i]);
map<string, vector<string > > m;
queue<string > q;
nv.insert(s);
q.push(s);
bool isFind = false;
while (! q.empty()) {
int size = q.size();
while (size -- > 0) {
string n = q.front();
string v = n;
q.pop();
for (i = 0; i < sn; i ++) {
for (char c = 'a'; c <= 'z'; c ++) {
v[i] = c;
if (! nv.count(v)) continue;
if (! hv.count(v)) {
hv.insert(v);
q.push(v);
}
m[v].push_back(n);
if (! v.compare(t)) isFind = true;
}
v[i] = n[i];
}
}
if (isFind) break;
for (set<string >::iterator iter = hv.begin(); iter != hv.end(); iter ++)
nv.erase(*iter);
hv.clear();
}
vector<string > v;
find(t, s, v, m, ans);
return ans;
}
};
int main() {
string g[] = {"hot","dot","dog","lot","log","cog"};
string s = "hit", t = "cog";
vector<string > w;
int i;
for (i = 0; i < (sizeof(g)/sizeof(g[0])); i ++) w.push_back(g[i]);
vector<vector<string > > ans = Solution().findLadders(s, t, w);
for (i = 0; i < ans.size(); i ++) {
cout<<"+++++++++"<<endl;
for (int j = 0; j < ans[i].size(); j ++) {
cout<<ans[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
Python Solution: github
#coding=utf-8
'''
url: leetcode.com/problems/word-ladder-ii
@author: zxwtry
@email: zxwtry@qq.com
@date: 2017年5月5日
@details: Solution: 86ms 36.12%
'''
from jinja2._compat import unichr
from re import search
class Solution(object):
def backtrace(self, m, b, e, rec, ans):
rec.insert(0, e)
if b == e:
ans.append(list(rec))
else:
for v in m[e]:
self.backtrace(m, b, v, rec, ans)
rec.remove(rec[0])
def findLadders(self, b, e, w):
"""
:type b: str
:type e: str
:type w: List[str]
:rtype: List[List[str]]
"""
n = 0 if b == None else len(b)
if n == 0: return [[""]]
nv, hv = set(w), set()
m = {w[i]:set() for i in range(len(w))}
m[b] = set()
nv.add(b)
q, isFind = [b], False
while len(q) != 0:
size = len(q)
while size > 0:
size = size-1
v = q.pop()
cs = [v[i] for i in range(n)]
for i in range(n):
for k in range(26):
cs[i] = unichr(97+k)
cc = "".join(cs)
if not (cc in nv): continue
if cc == e: isFind = True
if (cc not in hv):
q.append(cc)
hv.add(cc)
m[cc].add(v)
cs[i] = v[i]
if isFind: break
for vv in hv: nv.remove(vv)
hv.clear()
ans, rec = [], []
print(m)
self.backtrace(m, b, e, rec, ans)
return ans
if __name__ == "__main__":
b = 'hit'
e = 'cog'
w = ["hot","dot","dog","lot","log","cog"]
print(Solution().findLadders(b, e, w))