39. 组合总和
题目链接/文章讲解: 代码随想录
//组合问题要考虑是不是在一个集合里操作
//最常见的就是递归回溯法
//再考虑考虑剪枝
class Solution{
public List<List<Integer>> combinationSum(int[] candidates, int target){
List<List<Integer>> ans = new ArrayList<>();
Arrays.sort(candidates);//先进行排序
backtracking(ans, new ArrayList<>(), candidates, target, 0, 0);
return ans;
}
public void backtracking(List<List<Integer>> ans, List<Integer> path, int[] candidates, int target, int sum, int index){
//找到了数字和为target的组合
//剪枝一下 如果当前sum + candidate[i] > target 可以直接不进行递归 不必多余判断
if(sum == target){
ans.add(new ArrayList<>(path));
return;
}
for(int i = index; i < candidates.length && candidates[i] + sum <= target; i++){
path.add(candidates[i]);
backtracking(ans, path, candidates, target, sum + candidates[i], i);
path.remove(path.size() - 1);//回溯 移除路径path最后一个元素
}
}
}
感觉稍微自己能理解一下回溯了 能跟着循环走一遍思路 对每个位置应该有的参数有了想法
40.组合总和II
题目链接/文章讲解: 代码随想录
集合里有重复元素 但是不能选出的组合不能有重复的 此时就要对 树层进行剪枝 树枝不需要剪枝
Java代码:
class Solution {
LinkedList<Integer> path = new LinkedList<>();
List<List<Integer>> ans = new ArrayList<>();
int sum = 0;
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
//先排序后递归剪枝回溯
Arrays.sort(candidates);
backtracking(candidates, target, 0);
return ans;
}
private void backtracking(int[] candidates, int target, int startindex){
if(sum == target){
ans.add(new ArrayList<>(path));
return;
}
for(int i = startindex; i < candidates.length && candidates[i] + sum <= target; i++){
//接下来树层剪枝 跳过同一树层的剪枝
if(i > startindex && candidates[i] == candidates[i - 1]){
continue;
}
sum += candidates[i];
path.add(candidates[i]);
// i + 1 代表当前组内元素只选一次 不重复选择
backtracking(candidates, target, i + 1);
int temp = path.getLast();
sum -= temp;//回溯
path.removeLast();
}
}
}
131.分割回文串
题目链接:131. 分割回文串 - 力扣(LeetCode)
讲解链接:代码随想录
这道题重点在于什么是分割 怎么转化为组合 怎么分割 怎么在递归循环里截取子串 子串里是否回文 需要多加练习
Java代码:
class Solution{
List<List<String>> ans = new ArrayList<>();
List<String> str = new ArrayList<>();
public List<List<String>> partition(String s){
backtracking(s, 0, new StringBuilder());
return ans;
}
private void backtracking(String s, int startindex, StringBuilder sb){
//因为起始位置一个一个加 所以结束时startindex一定等于s.length,
//因为进入backtracking时
//一定末尾也是回文 所以str是满足条件的
if(startindex == s.length()){
ans.add(new ArrayList<>(str));
return;
}
//从后往前搜索 如果发现回文 进入backtracking 起始位置后移动一位 循环结束
for(int i = startindex ; i < s.length(); i++){
sb.append(s.charAt(i));
if(check(sb)){
str.add(sb.toString());
backtracking(s, i + 1, new StringBuilder());
str.remove(str.size() - 1);
}
}
}
private boolean check(StringBuilder sb){
for(int i = 0; i < sb.length() / 2; i++){
if(sb.charAt(i) != sb.charAt(sb.length() - i - 1)) return false;
}
return true;
}
}
741

被折叠的 条评论
为什么被折叠?



