一句话总结:还是感觉回溯很难。
原题链接:216 组合总和III
主要内容是原题解,做了些许剪枝工作,如在n < k * (k + 1) / 2 || n > 45时无解,直接返回空ans即可。
class Solution {
private List<List<Integer>> ans = new ArrayList<>();
private List<Integer> path = new ArrayList<>();
public List<List<Integer>> combinationSum3(int k, int n) {
if (n < k * (k + 1) / 2 || n > 45) return ans;
backtrack(1, 9, k, n);
return ans;
}
private void backtrack(int start, int n, int k, int target) {
if (path.size() > k || path.size() + n - start + 1 < k) return;
if (path.size() == k) {
int sum = 0;
for (int x : path) sum += x;
if (sum == target) {
ans.add(new ArrayList<Integer>(path));
return;
}
}
path.add(start);
backtrack(start + 1, 9, k, target);
path.removeLast();
backtrack(start + 1, 9, k, target);
}
}
原题链接:17 电话号码的字母组合
需要先利用哈希表保存每个按键对应的几个字母,然后就是回溯三部曲递归一下。
class Solution {
List<String> ans = new ArrayList<>();
Map<Character,String> map = new HashMap<>(){{
put('2',"abc");
put('3',"def");
put('4',"ghi");
put('5',"jkl");
put('6',"mno");
put('7',"pqrs");
put('8',"tuv");
put('9',"wxyz");
}};
public List<String> letterCombinations(String digits) {
if(digits.length() == 0){
return ans;
}
StringBuilder path = new StringBuilder();
dfs(path, map, digits, 0);
return ans;
}
public void dfs(StringBuilder path, Map<Character, String> map, String digits, int depth){
if (depth == digits.length()) {
ans.add(path.toString());
} else {
char dight = digits.charAt(depth);
String str = map.get(dight);
int len = str.length();
for (int i = 0; i < len; i++) {
path.append(str.charAt(i));
dfs(path, map, digits, depth + 1);
path.deleteCharAt(depth);
}
}
}
}