LeetCode link
first thought
the same as word ladder problem, just need to record paths to the current word
solution
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
public class Solution {
public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) {
Map<String, List<List<String>>> map = new HashMap<>();
for (String word: wordList) {
map.put(word, new ArrayList<List<String>>());
}
List<List<String>> beginList = new ArrayList<>();
List<String> begin = new ArrayList<>();
begin.add(beginWord);
beginList.add(begin);
map.put(beginWord, beginList);
Queue<String> queue = new LinkedList<>();
queue.add(beginWord);
while (!queue.isEmpty()) {
String word = queue.poll();
ArrayList list = (ArrayList)map.get(word);
char[] chars = word.toCharArray();
for (int i = 0; i < word.length(); i++) {
char originalChar = chars[i];
for (char c = 'a'; c <= 'z'; c++) {
if (c == originalChar) {
continue;
}
chars[i] = c;
String newStr = new String(chars);
if (map.containsKey(newStr)) {
ArrayList newStrList = (ArrayList)map.get(newStr);
if (this.isNeedUpdate(newStrList, list)) {
newStrList.clear();
for (int j = 0; j < list.size(); j++) {
ArrayList<String> tempList = (ArrayList)(list.get(j));
List<String> newList = new ArrayList(tempList);
newList.add(newStr);
newStrList.add(newList);
}
map.put(newStr, newStrList);
if (!newStr.equals(endWord)) {
queue.add(newStr);
}
}
}
}
chars[i] = originalChar;
}
}
return map.get(endWord) == null ? new ArrayList<>() : map.get(endWord);
}
private boolean isNeedUpdate(ArrayList<ArrayList<String>> newStrList, ArrayList<ArrayList<String>> list) {
if (newStrList.size() < 1) {
return true;
}
ArrayList newStrList0 = newStrList.get(0);
ArrayList list0 = list.get(0);
if (newStrList0.size() > list0.size() + 1 || (newStrList0.size() == list0.size() + 1 && newStrList.size() < list.size())) {
return true;
}
return false;
}
}
problem wrong answer
Your input “hit” “cog” [“hot”,”dot”,”dog”,”lot”,”log”,”cog”]
Your answer [[“hit”,”hot”,”dot”,”dog”,”cog”]]
Expected answer [[“hit”,”hot”,”lot”,”log”,”cog”],[“hit”,”hot”,”dot”,”dog”,”cog”]]
reason
it seems missing answers, maybe during the update part.
modification
when the path size is equal, should not to clear all the list, if not so, it would clear the previous valid paths.
change the outer list to set, to make sure there’s no duplicate in iterating.
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
public class Solution {
public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) {
Map<String, Set<List<String>>> map = new HashMap<>();
Map<String, Integer> distance = new HashMap<>();
for (String word: wordList) {
map.put(word, new HashSet<List<String>>());
distance.put(word, Integer.MAX_VALUE);
}
Set<List<String>> beginList = new HashSet<>();
List<String> begin = new ArrayList<>();
begin.add(beginWord);
beginList.add(begin);
map.put(beginWord, beginList);
Queue<String> queue = new LinkedList<>();
queue.add(beginWord);
distance.put(beginWord, 1);
while (!queue.isEmpty()) {
String word = queue.poll();
HashSet list = (HashSet)map.get(word);
char[] chars = word.toCharArray();
for (int i = 0; i < word.length(); i++) {
char originalChar = chars[i];
for (char c = 'a'; c <= 'z'; c++) {
if (c == originalChar) {
continue;
}
chars[i] = c;
String newStr = new String(chars);
if (map.containsKey(newStr)) {
HashSet newStrList = (HashSet)map.get(newStr);
boolean isNeedUpdate = false;
if (newStrList.size() < 1) {
isNeedUpdate = true;
newStrList.clear();
} else {
if (distance.get(newStr) > distance.get(word) + 1) {
isNeedUpdate = true;
newStrList.clear();
} else if (distance.get(newStr) == distance.get(word) + 1 && newStrList.size() < list.size()) {
isNeedUpdate = true;
}
}
if (isNeedUpdate) {
Iterator iter = list.iterator();
while (iter.hasNext()) {
ArrayList tempList = (ArrayList)iter.next();
List<String> newList = new ArrayList(tempList);
newList.add(newStr);
newStrList.add(newList);
}
map.put(newStr, newStrList);
if (!newStr.equals(endWord)) {
queue.add(newStr);
}
}
}
}
chars[i] = originalChar;
}
}
if (map.get(endWord) == null) {
return new ArrayList<>();
}
ArrayList<List<String>> result = new ArrayList<>();
Iterator iter = ((HashSet)map.get(endWord)).iterator();
while (iter.hasNext()) {
ArrayList list = (ArrayList)iter.next();
result.add(list);
}
return result;
}
}
problem
Surely TLE…
reason
full of sets…
modification
have seen the answer, the main idea of this problem is maintain a map of each word’s prewordlist, and using dfs to recursive the paths to the end.
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
public class Solution {
public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) {
List<List<String>> result = new ArrayList<>();
Set<String> wordSet = new HashSet<>();
for (String word: wordList) {
wordSet.add(word);
}
Map<String, List<String>> preWords = new HashMap<>();
Queue<String> queue = new LinkedList<>();
boolean hasFound = false;
queue.add(beginWord);
wordSet.remove(beginWord);
while (!queue.isEmpty() && wordSet.size() > 0) {
Queue<String> queue2 = new LinkedList<>();
while (!queue.isEmpty() && wordSet.size() > 0) {
String str = queue.poll();
List<String> validWords = this.validWords(str, wordSet);
for (String newStr: validWords) {
List<String> list = new ArrayList<>();
if (preWords.containsKey(newStr)) {
list = preWords.get(newStr);
}
list.add(str);
preWords.put(newStr, list);
if (newStr.equals(endWord)) {
hasFound = true;
}
if (!hasFound) {
queue2.add(newStr);
}
}
}
if (!hasFound) {
queue = queue2;
}
}
List<String> path = new ArrayList<>();
path.add(endWord);
this.dfs(preWords, endWord, path, result);
return result;
}
private List<String> validWords(String str, Set<String> wordSet) {
List<String> words = new ArrayList<>();
char[] chars = str.toCharArray();
for (int i = 0; i < chars.length; i++) {
char original = chars[i];
for (char c = 'a'; c <= 'z'; c++) {
if (c != original) {
chars[i] = c;
String newStr = new String(chars);
if (wordSet.contains(newStr)) {
wordSet.remove(newStr);
words.add(newStr);
}
}
}
chars[i] = original;
}
return words;
}
private void dfs(Map<String, List<String>> map, String word, List<String> path, List<List<String>> result) {
if (!map.containsKey(word)) {
if (path.size() > 1) {
List<String> newPath = new ArrayList<>(path);
Collections.reverse(newPath);
result.add(newPath);
return;
}
}
List<String> pre = map.get(word);
for (String s: pre) {
path.add(s);
this.dfs(map, s, path, result);
path.remove(path.size() - 1);
}
}
}
problem
wrong answer, missing answers
reason
the timing of delete the wordSet is not proper.
modification
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
while (!queue.isEmpty() && wordSet.size() > 0) {
Queue<String> queue2 = new LinkedList<>();
List<String> temp = new ArrayList<>();
while (!queue.isEmpty() && wordSet.size() > 0) {
String str = queue.poll();
List<String> validWords = this.validWords(str, wordSet);
temp.addAll(validWords);
for (String newStr: validWords) {
List<String> list = new ArrayList<>();
if (preWords.containsKey(newStr)) {
list = preWords.get(newStr);
}
list.add(str);
preWords.put(newStr, list);
if (newStr.equals(endWord)) {
hasFound = true;
}
if (!hasFound) {
queue2.add(newStr);
}
}
}
wordSet.removeAll(temp);
if (!hasFound) {
queue = queue2;
}
}
problem
duplicated answers…
Input: “red” “tax” [“ted”,”tex”,”red”,”tax”,”tad”,”den”,”rex”,”pee”] Output: [[“red”,”ted”,”tad”,”tax”],[“red”,”ted”,”tex”,”tax”],[“red”,”rex”,”tex”,”tax”],[“red”,”ted”,”tex”,”tax”],[“red”,”rex”,”tex”,”tax”]] Expected: [[“red”,”ted”,”tad”,”tax”],[“red”,”ted”,”tex”,”tax”],[“red”,”rex”,”tex”,”tax”]]
reason
still the timing.
not the timing, it because queue2 may contain duplicated strings. some words in one layer may produce the same word, so the word be added to queue2 for several times.
modification
change queue2 to a set.
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
public class Solution {
public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) {
List<List<String>> result = new ArrayList<>();
Set<String> wordSet = new HashSet<>();
for (String word: wordList) {
wordSet.add(word);
}
Map<String, List<String>> preWords = new HashMap<>();
Queue<String> queue = new LinkedList<>();
boolean hasFound = false;
queue.add(beginWord);
wordSet.remove(beginWord);
while (!queue.isEmpty() && wordSet.size() > 0) {
Set<String> queue2 = new HashSet<>();
while (!queue.isEmpty() && wordSet.size() > 0) {
String str = queue.poll();
List<String> validWords = this.validWords(str, wordSet);
for (String newStr: validWords) {
if (!preWords.containsKey(newStr)) {
preWords.put(newStr, new ArrayList<String>());
}
preWords.get(newStr).add(str);
if (newStr.equals(endWord)) {
hasFound = true;
}
queue2.add(newStr);
}
}
wordSet.removeAll(queue2);
if (!hasFound) {
queue.addAll(queue2);
}
}
List<String> path = new ArrayList<>();
path.add(endWord);
this.dfs(preWords, endWord, path, result);
return result;
}
private List<String> validWords(String str, Set<String> wordSet) {
List<String> words = new ArrayList<>();
char[] chars = str.toCharArray();
for (int i = 0; i < chars.length; i++) {
char original = chars[i];
for (char c = 'a'; c <= 'z'; c++) {
if (c != original) {
chars[i] = c;
String newStr = new String(chars);
if (wordSet.contains(newStr)) {
words.add(newStr);
}
}
}
chars[i] = original;
}
return words;
}
private void dfs(Map<String, List<String>> map, String word, List<String> path, List<List<String>> result) {
if (!map.containsKey(word)) {
if (path.size() > 1) {
List<String> newPath = new ArrayList<>(path);
Collections.reverse(newPath);
result.add(newPath);
}
return;
}
List<String> pre = map.get(word);
for (String s: pre) {
path.add(s);
this.dfs(map, s, path, result);
path.remove(path.size() - 1);
}
}
}
近期评论