39. 组合总和
题目链接/文章讲解:代码随想录
数组中无重复元素,集合里元素可重复
class Solution {
//未排序
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
int sum = 0;
public List<List<Integer>> combinationSum(int[] candidates, int target) {
backTracking(candidates, target, 0);
return res;
}
public void backTracking(int[] candidates, int target, int index) {
if(sum > target) return;
if(sum == target) {
res.add(new ArrayList<>(path));
return;
}
for(int i = index; i < candidates.length; i++) {
path.add(candidates[i]);
sum += candidates[i];
backTracking(candidates, target, i);
path.removeLast();
sum -= candidates[i];
}
}
}
class Solution {
//排序
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
int sum = 0;
public List<List<Integer>> combinationSum(int[] candidates, int target) {
Arrays.sort(candidates);
backTracking(candidates, target, 0);
return res;
}
public void backTracking(int[] candidates, int target, int index) {
if(sum == target) {
res.add(new ArrayList<>(path));
return;
}
for(int i = index; i < candidates.length && sum + candidates[i] <= target; i++) {//剪枝 因为已排序,所以可以确定后面没有更小的
path.add(candidates[i]);
sum += candidates[i];
backTracking(candidates, target, i);
path.removeLast();
sum -= candidates[i];
}
}
}
40.组合总和II
题目链接/文章讲解:代码随想录
数组有重复,集合元素可重复,集合不重复,需要去重
树枝去重 树层去重
使用used
class Solution {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
boolean[] used;
int sum = 0;
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
used = new boolean[candidates.length];
Arrays.fill(used,false);
Arrays.sort(candidates);
backTracking(candidates, target, 0);
return res;
}
public void backTracking(int[] candidates, int target, int index) {
if(sum == target) {
res.add(new ArrayList<>(path));
return;
}
for(int i = index; i < candidates.length; i++) {
if(sum + candidates[i] > target) break;
if(i > 0 && candidates[i] == candidates[i-1] && !used[i-1]) continue;//树层剪枝
path.add(candidates[i]);
sum += candidates[i];
used[i] = true;
backTracking(candidates, target, i+1);
used[i] = false;
sum -= candidates[i];
path.remove(path.size() - 1);
}
}
}
没有使用used
class Solution {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
int sum = 0;
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
Arrays.sort(candidates);
backTracking(candidates, target, 0);
return res;
}
public void backTracking(int[] candidates, int target, int index) {
if(sum == target) {
res.add(new ArrayList<>(path));
return;
}
for(int i = index; i < candidates.length && sum + candidates[i] <= target; i++) {//树层与树枝剪枝
if(i > index && candidates[i] == candidates[i-1]) continue;//树层剪枝
path.add(candidates[i]);
sum += candidates[i];
backTracking(candidates, target, i+1);
sum -= candidates[i];
path.remove(path.size() - 1);
}
}
}
131.分割回文串
如何进行分割:用startIndex进行分割,采用双指针,for循环中i为终止位置,i的取值范围为startIndex--s.length(),左闭右开。for循环如果出现回文串,从i+1为起始位置进行下一级纵向递归,回溯
判断回文串:双指针
class Solution {
List<List<String>> res = new ArrayList<>();
Deque<String> path = new LinkedList<>();
public List<List<String>> partition(String s) {
backTracking(s,0);
return res;
}
public void backTracking(String s, int startIndex){
if(startIndex == s.length()) {//终止条件 起始位置从0开始,当等于s的长度,说明已经遍历过一遍
res.add(new ArrayList<>(path));
return;
}
for(int i = startIndex; i < s.length(); i++) {//横向 树层
if(isPalindrome(startIndex, i, s)) {//判断是否是回文串 双指针 起始位置是startIndex 终止位置是i
String str = s.substring(startIndex, i+1);//如果是回文串,截取字符串
path.addLast(str);
} else {
continue;//continue是跳过当次循环进入下次循环 break是跳出循环 return是跳出方法
}
backTracking(s, i+1);//纵向 树枝
path.removeLast();//回溯
}
}
public boolean isPalindrome(int startIndex, int end, String s) {//判断回文串
for(int i = startIndex, j = end; i < j; i++, j--) {//双指针
if(s.charAt(i) != s.charAt(j)) {
return false;
}
}
return true;
}
}