17. Letter Combinations of a Phone Number
给一串数字,获得按照手机键盘上对应的字母的所有组合。
Input: “23”
Output: [“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”].
用回溯法:
HashMap<Integer, String> map = new HashMap<>();
public List<String> letterCombinations(String digits) {
if (digits.length() < 1) return Collections.emptyList();
map.put(2, "abc");
map.put(3, "def");
map.put(4, "ghi");
map.put(5, "jkl");
map.put(6, "mno");
map.put(7, "pqrs");
map.put(8, "tuv");
map.put(9, "wxyz");
help(digits, new StringBuffer(""), 0);
return res;
}
List<String> res = new ArrayList<>();
public void help(String digits, StringBuffer str, int index) {
if (digits.length() == str.length())
res.add(str.toString());
else {
//每次递归时获得当前数字对应的所以字母,并遍历它们
String temp = map.get(digits.charAt(index) - '0');
for (int i = 0; i < temp.length(); i++) {
str.append(temp.charAt(i));
help(digits, str, index+1);
//在回溯时去掉刚才加入的字符
str.deleteCharAt(str.length()-1);
}
}
}
39. Combination Sum
给一个没有重复数的数组,和一个target,求数组中能组合成target(每个数字可以重复使用)的组合个数。
Input: candidates = [2,3,6,7], target = 7,
A solution set is:
[ [7], [2,2,3] ]
也是回溯法,但和上面的区别是数组中每个元素可以重复使用,所以有细微区别:遍历时的指标index不随每次循环递增,而是当每次获得一个解时再增加:
public List<List<Integer>> combinationSum(int[] candidates, int target) {
Arrays.sort(candidates);
help(candidates, target, 0, 0, new ArrayList<>());
return res;
}
List<List<Integer>> res = new ArrayList<>();
public void help(int[] candidates, int target, int index, int sum, List<Integer> nums) {
if (sum == target) {
//不能直接将nums加入到res解列表中,因为nums也是一个列表,所以每次add到res中的列表指向的都是同一个对象。
//然后在程序执行中,它作为一个参数,其中的值是一直在变化的,在程序结束时nums会回归到空列表,那么添加进res的就都是空列表了。
List<Integer> temp = new ArrayList<>(nums);
res.add(temp);
} else {
for (; index < candidates.length; ) {
if (sum + candidates[index] <= target) {
nums.add(candidates[index]);
help(candidates, target, index, sum + candidates[index], nums);
//获得一个解后index加一
nums.remove(nums.size()-1);
index++;
}else {
//因为数组已经有序,所以当遇到一个sum大于target的元素后,剩下的元素就都不用看了
break;
}
}
}
}