1-
2-
31import java .util .ArrayList ;
2+ import java .util .HashMap ;
43import java .util .HashSet ;
5- import java .util .LinkedList ;
6- import java .util .Queue ;
4+ import java .util .Map ;
75
86/**
97 * Given two words (start and end), and a dictionary, find all shortest
2321 */
2422
2523public class WordLadderII {
24+ private void GeneratePath (Map <String , ArrayList <String >> prevMap ,
25+ ArrayList <String > path , String word ,
26+ ArrayList <ArrayList <String >> ret ) {
27+ if (prevMap .get (word ).size () == 0 ) {
28+ path .add (0 , word );
29+ ArrayList <String > curPath = new ArrayList <String >(path );
30+ ret .add (curPath );
31+ path .remove (0 );
32+ return ;
33+ }
34+
35+ path .add (0 , word );
36+ for (String pt : prevMap .get (word )) {
37+ GeneratePath (prevMap , path , pt , ret );
38+ }
39+ path .remove (0 );
40+ }
41+
2642 public ArrayList <ArrayList <String >> findLadders (String start , String end ,
2743 HashSet <String > dict ) {
2844 ArrayList <ArrayList <String >> ret = new ArrayList <ArrayList <String >>();
29- int currentLevel = 1 , nextLevel = 0 ;
30- boolean found = false ;
31- HashSet <String > visited = new HashSet <String >();
45+ Map <String , ArrayList <String >> prevMap = new HashMap <String , ArrayList <String >>();
46+ dict .add (start );
47+ dict .add (end );
48+ for (String d : dict ) {
49+ prevMap .put (d , new ArrayList <String >());
50+ }
51+ ArrayList <HashSet <String >> candidates = new ArrayList <HashSet <String >>();
52+ candidates .add (new HashSet <String >());
53+ candidates .add (new HashSet <String >());
54+ int current = 0 ;
55+ int previous = 1 ;
56+ candidates .get (current ).add (start );
57+ while (true ) {
58+ current = current == 0 ? 1 : 0 ;
59+ previous = previous == 0 ? 1 : 0 ;
60+ for (String d : candidates .get (previous )) {
61+ dict .remove (d );
62+ }
63+ candidates .get (current ).clear ();
64+ for (String wd : candidates .get (previous )) {
65+ for (int pos = 0 ; pos < wd .length (); ++pos ) {
66+ StringBuffer word = new StringBuffer (wd );
67+ for (int i = 'a' ; i <= 'z' ; ++i ) {
68+ if (wd .charAt (pos ) == i ) {
69+ continue ;
70+ }
3271
33- Queue <String > q = new LinkedList <String >();
34- q .add (start );
35- Queue <ArrayList <String >> sequences = new LinkedList <ArrayList <String >>();
36- ArrayList <String > l = new ArrayList <String >();
37- l .add (start );
38- sequences .add (l );
72+ word .setCharAt (pos , (char ) i );
3973
40- while (!q .isEmpty ()) {
41- String st = q .remove ();
42- ArrayList <String > tmp = sequences .remove ();
43- currentLevel --;
44- if (st .equals (end )) {
45- ret .add (tmp );
46- found = true ;
47- } else {
48- if (!found ) {
49- for (int i = 0 ; i < st .length (); i ++) {
50- StringBuffer sb = new StringBuffer (st );
51- for (int j = 0 ; j < 26 ; j ++) {
52- sb .setCharAt (i , (char ) ('a' + j ));
53- String next = sb .toString ();
54- boolean in = false ;
55- for (int g = 0 ; g < tmp .size (); g ++)
56- if (tmp .get (g ).equals (next )) {
57- in = true ;
58- break ;
59- }
60- if (dict .contains (next ) && !in ) {
61- q .add (next );
62- visited .add (next );
63- nextLevel ++;
64- ArrayList <String > nexttmp = new ArrayList <String >(
65- tmp );
66- nexttmp .add (next );
67- sequences .add (nexttmp );
68- }
74+ if (dict .contains (word .toString ())) {
75+ prevMap .get (word .toString ()).add (wd );
76+ candidates .get (current ).add (word .toString ());
6977 }
7078 }
7179 }
7280 }
73- if (currentLevel == 0 ) {
74- if (found )
75- break ;
76- else {
77- currentLevel = nextLevel ;
78- nextLevel = 0 ;
79- }
81+
82+ if (candidates .get (current ).size () == 0 ) {
83+ return ret ;
84+ }
85+ if (candidates .get (current ).contains (end )) {
86+ break ;
8087 }
8188 }
8289
90+ ArrayList <String > path = new ArrayList <String >();
91+ GeneratePath (prevMap , path , end , ret );
92+
8393 return ret ;
8494 }
8595}
0 commit comments