求和组合与电话号码的字母组合
做算法题,画图很关键,特别是递归回溯这类题,“三步走”中第三步递归是如何进行的是很关键的,其他两步好解决,pram也可根据第三步来确定
一、求和组合
- 注意path得用LinkedList, List类没有removeLast方法,直接用有些麻烦
- 回溯操作是组合问题很关键的一步,可以减少时间复杂度,否者真和暴力求解无异了
- 这里有两个剪枝操作
class Solution {
List<List<Integer>> result ;
LinkedList<Integer> path; // todo path得用LinkedList,要不然灭有封装removeLast方法
public List<List<Integer>> combinationSum3(int k, int n) {
result = new ArrayList<>();
path = new LinkedList<>();
travelbacking( n,k,0,1);
return result;
}
// 返回值用void, 不需要统计调用次数
public void travelbacking(int target,int k,int sum,int startIndex ){
// 剪枝
if (sum > target) {
return;
}
if(target == sum && path.size() == k){
result.add(new ArrayList<>(path));
// sum = 0; // 这里sum不用归零
return ;
}
for (int i = startIndex; i <= 9 - (k - path.size()) + 1; i++) { // 注意这里没有直接修改startIndex
path.add(i);
sum += i;
travelbacking(target,k,sum,i+1); // startindex要写这!
path.removeLast();
sum-= i; // 一定要进行回溯
}
}
}
电话号码的字母组合
- 不同集合的字母组合
- 字符串的处理也是值得关注的点
class Solution {
LinkedList<String> path;
List<String> result; // 新增一个变量来存储最终结果
public List<String> letterCombinations(String digits) {
path = new LinkedList<>();
result = new LinkedList<>(); // 初始化结果列表
if (digits == null || digits.length() == 0) {
return result;
}
// 初始对应所有的数字
String[] numString = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
travelbacking(digits, numString, 0);
return result;
}
public void travelbacking(String digits, String[] numString, int digitIndex) {
// 当路径长度等于输入数字长度时,说明已经完成了一种组合
if (digitIndex == digits.length()) {
result.add(String.join("", path)); // 将当前路径转换为字符串并加入结果列表
return;
}
String str = numString[digits.charAt(digitIndex) - '0']; // 获取当前数字对应的字母字符串
for (char c : str.toCharArray()) { // 遍历该数字对应的每个字母
path.add(Character.toString(c)); // 添加字母到路径中
travelbacking(digits, numString, digitIndex + 1); // 递归处理下一个数字
path.removeLast(); // 回溯,移除最后一个字母准备尝试下一个
}
}
}