本篇给出Combination Sum 和Word Ladder 这两种题型。
Combination Sum
这道题为给出一个数组,使用数组中的数组成和为k的组合。使用前面提到的深度搜索,类似于第一篇提到的方法。
public ArrayList<ArrayList<Integer>> combinationSum(int[] candidates, int target) {
ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
if (candidates == null) {
return result;
}
ArrayList<Integer> path = new ArrayList<Integer>();
Arrays.sort(candidates);
helper(candidates, target, path, 0, result);
return result;
}
void helper(int[] candidates, int target, ArrayList<Integer> path, int index,
ArrayList<ArrayList<Integer>> result) {
if (target == 0) {
result.add(new ArrayList<Integer>(path));
return;
}
int prev = -1;
for (int i = index; i < candidates.length; i++) {
if (candidates[i] > target) {
break;
}
if (prev != -1 && prev == candidates[i]) {
continue;
}
path.add(candidates[i]);
helper(candidates, target - candidates[i], path, i, result);
path.remove(path.size() - 1);
prev = candidates[i];
}
}
Combination Sum II
这道题也是求组合,不同点在于数组中的数只能使用一次。因此,在下一次搜索时index+1即可。
private ArrayList<ArrayList<Integer>> results;
public ArrayList<ArrayList<Integer>> combinationSum2(int[] candidates,
int target) {
if (candidates.length < 1) {
return results;
}
ArrayList<Integer> path = new ArrayList<Integer>();
java.util.Arrays.sort(candidates);
results = new ArrayList<ArrayList<Integer>> ();
combinationSumHelper(path, candidates, target, 0);
return results;
}
private void combinationSumHelper(ArrayList<Integer> path, int[] candidates, int sum, int pos) {
if (sum == 0) {
results.add(new ArrayList<Integer>(path));
}
if (pos >= candidates.length || sum < 0) {
return;
}
int prev = -1;
for (int i = pos; i < candidates.length; i++) {
if (candidates[i] != prev) {
path.add(candidates[i]);
combinationSumHelper(path, candidates, sum - candidates[i], i + 1);
prev = candidates[i];
path.remove(path.size()-1);
}
}
}
Word Ladder
这道题是求一个单词变成另一个单词的最少次数,变化过程中的单词必须是词典中的单词。求最少次数这道题可以使用广度搜索,类似于层序遍历,找到第一个即是最短的。
public int ladderLength(String start, String end, Set<String> dict) {
if (dict == null) {
return 0;
}
if (start.equals(end)) {
return 1;
}
dict.add(start);
dict.add(end);
HashSet<String> hash = new HashSet<String>();
Queue<String> queue = new LinkedList<String>();
queue.offer(start);
hash.add(start);
int length = 1;
while(!queue.isEmpty()) {
length++;
int size = queue.size();
for (int i = 0; i < size; i++) {
String word = queue.poll();
for (String nextWord: getNextWords(word, dict)) {
if (hash.contains(nextWord)) {
continue;
}
if (nextWord.equals(end)) {
return length;
}
hash.add(nextWord);
queue.offer(nextWord);
}
}
}
return 0;
}
private String replace(String s, int index, char c) {
char[] chars = s.toCharArray();
chars[index] = c;
return new String(chars);
}
private ArrayList<String> getNextWords(String word, Set<String> dict) {
ArrayList<String> nextWords = new ArrayList<String>();
for (char c = 'a'; c <= 'z'; c++) {
for (int i = 0; i < word.length(); i++) {
if (c == word.charAt(i)) {
continue;
}
String nextWord = replace(word, i, c);
if (dict.contains(nextWord)) {
nextWords.add(nextWord);
}
}
}
return nextWords;
}
Word Ladder II
这道题求最少变换的过程。上面题求最少变换次数使用广搜,那么这道题求过程需要在广搜里面插入深度搜索。
public List<List<String>> findLadders(String start, String end,Set<String> dict) {
List<List<String>> ladders = new ArrayList<List<String>>();
Map<String, List<String>> map = new HashMap<String, List<String>>();
Map<String, Integer> distance = new HashMap<String, Integer>();
dict.add(start);
dict.add(end);
bfs(map, distance, start, end, dict);
List<String> path = new ArrayList<String>();
dfs(ladders, path, end, start, distance, map);
return ladders;
}
void dfs(List<List<String>> ladders, List<String> path, String crt,
String start, Map<String, Integer> distance,
Map<String, List<String>> map) {
path.add(crt);
if (crt.equals(start)) {
Collections.reverse(path);
ladders.add(new ArrayList<String>(path));
Collections.reverse(path);
} else {
for (String next : map.get(crt)) {
if (distance.containsKey(next) && distance.get(crt) == distance.get(next) + 1) {
dfs(ladders, path, next, start, distance, map);
}
}
}
path.remove(path.size() - 1);
}
void bfs(Map<String, List<String>> map, Map<String, Integer> distance,
String start, String end, Set<String> dict) {
Queue<String> q = new LinkedList<String>();
q.offer(start);
distance.put(start, 0);
for (String s : dict) {
map.put(s, new ArrayList<String>());
}
while (!q.isEmpty()) {
String crt = q.poll();
List<String> nextList = expand(crt, dict);
for (String next : nextList) {
map.get(next).add(crt);
if (!distance.containsKey(next)) {
distance.put(next, distance.get(crt) + 1);
q.offer(next);
}
}
}
}
List<String> expand(String crt, Set<String> dict) {
List<String> expansion = new ArrayList<String>();
for (int i = 0; i < crt.length(); i++) {
for (char ch = 'a'; ch <= 'z'; ch++) {
if (ch != crt.charAt(i)) {
String expanded = crt.substring(0, i) + ch + crt.substring(i + 1);
if (dict.contains(expanded)) {
expansion.add(expanded);
}
}
}
}
return expansion;
}