题目链接: 39. 组合总和
题目链接/文章讲解 : 代码随想录
看完代码随想录之后的想法
依旧可以画出相应的树图,每次选择出一个数,再递归选择下一个数的时候,不能选择该数之前的,但是可以选择该数;
终止条件,当和> target终止,当和==target满足条件终止;
单次循环逻辑,for循环里元素集合需要startIndex,
for {
然后处理该数值
再进行递归
然后进行回溯
}
同时,我们先对数组进行排序,就可以进行剪枝;sum + candidates[i] <= target;
因为如果大于target 就不用再看后面的数了;
class Solution {
LinkedList<Integer> path = new LinkedList<>();
List<List<Integer>> result = new LinkedList<>();
void backTracking(int sum, int target, int[] candidates, int startIndex) {
if(sum > target) return ;
if(sum == target) result.add(new LinkedList<>(path));
for(int i = startIndex;
i < candidates.length && sum + candidates[i] <= target; i++) {
path.add(candidates[i]);
sum += candidates[i];
backTracking(sum, target, candidates, i);
path.pollLast();
sum -= candidates[i];
}
}
public List<List<Integer>> combinationSum(int[] candidates, int target) {
Arrays.sort(candidates);
backTracking(0, target, candidates, 0);
return result;
}
}
题目链接:● 40.组合总和
文章讲解:代码随想录_27. 移除元素
看完代码随想录之后的想法:
依旧是回溯三部曲;
终止条件:sum > target
sum == target
单次循环条件;
for{
每一次选一个数, sum + candidates[i];
同时标记该数已访问;
把该数加入path;
递归
回溯;
}
我们要注意去重,我们不需要对树枝去重,因为树枝中的数并不是重复利用了
我们仅仅需要对树层进行去重;因为树层会重复;这时我们如何判断时树层还是树枝重复呢;我们需要使用used 数组,当我们每次处理一个数,把这个数标记已经访问,下一数访问的时候,
如果candidates[i] == candidates[i - 1] && used[i - 1] == 0 ,说明是数层重复;,就可以跳过,进行下一个操作;
class Solution {
LinkedList<Integer> path = new LinkedList<>();
List<List<Integer>> result = new LinkedList<>();
void backTracking(int[] candidates, int sum,
int target,int[] used, int startIndex) {
if(sum > target) return ;
if(sum == target) result.add(new LinkedList<>(path));
for(int i = startIndex; i < candidates.length; i++) {
if(i > 0 && candidates[i] == candidates[i - 1] && used[i - 1] == 0)
continue;
path.add(candidates[i]);
sum += candidates[i];
used[i] = 1;
backTracking(candidates, sum, target, used, i + 1);
path.pollLast();
sum -= candidates[i];
used[i] = 0;
}
}
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
int[] used = new int[candidates.length];
Arrays.sort(candidates);
backTracking(candidates, 0, target, used, 0);
return result;
}
}
题目链接:● 131.分割回文串
void backtracking(参数) {
if (终止条件) {
存放结果;
return;
}
for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
处理节点;
backtracking(路径,选择列表); // 递归
回溯,撤销处理结果
}
}
依旧是三部曲,
startIndex ,是确定元素的开始位置,
如果开始位置在s的最后一位的后面,说明需要终止了startIndex == s.size();
for{
startIndex 到 i ,这是一个字串,我们需要判断该字串是不是一个回文串;如果是,就放入reusult;
如果不是,我们没有必要继续往下深度递归了,我们就跳过,我们需要横向判断下一个字串是否是回文串;
然后是的话就递归;
然后回溯;
}
当然,卡哥说在判断是否是回文串的时候,可以使用动态规划,tmd,真不会哈哈