LeetCode 216.组合总和III
本题和LeetCode77有相似之处,只是回溯算法的递归终止条件需要判断当前k个数之和是否等于n。代码如下:
class Solution {
LinkedList<Integer> path = new LinkedList<>();
List<List<Integer>> result = new ArrayList<>();
int sum = 0;
public List<List<Integer>> combinationSum3(int k, int n) {
backtracking(n,k,1);
return result;
}
public void backtracking(int n, int k, int start) {
// 剪枝
if(sum > n) return;
if(path.size() == k) {
if(sum == n) {
result.add(new ArrayList(path));
}
return;
}
for(int i=start; i<=9 - (k - path.size()) + 1; i++) {
path.add(i);
sum += i;
backtracking(n, k, i+1);
sum -= path.getLast();
path.removeLast();
}
}
}
剪枝操作:
1.当sum大于n时,已经不需要再遍历了:if(sum > n) return;
2.同LeetCode77,可以对for循环进行剪枝,i<=9应写为9-(k-path.size())+1,因为再往后,凑不齐k个数了,就无需遍历。
LeetCode 17.电话号码的字母组合
本题需要解决以下3个问题:
1.数字和字母如何映射;
2.如何根据数字字符串的长度实现嵌套循环;
3.处理输入0 1 * #等特殊按键情况(本题并不要求处理,但在面试中可能要求处理)。
思路:用二维字符串数组根据数字的值作为下标来取对应的字母字符串,使用回溯法来灵活处理根据数字字符串长度个for循环的问题。
需要注意处理输入为空的边界情况,不然会出现空指针的错误。StringBuilder转String用toString方法就可以,撤销回溯操作时也要注意字符串下标不要越界。本题直接套用回溯法的模版还算比较简单,但要注意细节的处理,二刷时希望还能理解并通过。代码如下:
class Solution {
List<String> result = new ArrayList<>();
StringBuilder s = new StringBuilder();
String[] letterMap = {
"", // 0
"", // 1
"abc", // 2
"def", // 3
"ghi", // 4
"jkl", // 5
"mno", // 6
"pqrs", // 7
"tuv", // 8
"wxyz", // 9
};
public List<String> letterCombinations(String digits) {
if(digits == null || digits.length() == 0) return result;
backtracking(digits, 0);
return result;
}
public void backtracking(String digits, int index){
if(index == digits.length()){
result.add(s.toString());
return;
}
int digit = digits.charAt(index) - '0';
String letters = letterMap[digit];
for(int i=0; i<letters.length(); i++){
s.append(letters.charAt(i));
backtracking(digits, index+1);
s.deleteCharAt(s.length() - 1);
}
}
}