39. 组合总和
39. 组合总和 - 力扣(LeetCode)
本题和之前组合题不同在于,可以取重复的值,那么for循环里的递归还是从i开始,另外没有规定取k个,那么递归结束条件就是sum==target即可,另外剪枝操作是先将数组排序,然后在for循环里加条件,如果sum>target就break,注意这个地方和之前的组合总和3不同
class Solution {
List<List<Integer>> result = new ArrayList<>();
List<Integer> path = new LinkedList<>();
public List<List<Integer>> combinationSum(int[] candidates, int target){
Arrays.sort(candidates);
backTracking(candidates, target, 0, 0);
return result;
}
public void backTracking(int[] candidates, int target, int sum, int startIndex) {
if (sum == target) {
result.add(new ArrayList<>(path));
return;
}
for (int i=startIndex; i<candidates.length; i++) {
sum += candidates[i];
if (sum > target) break;
path.add(candidates[i]);
//因为是可以重复的,所以从i开始
backTracking(candidates, target, sum, i);
sum -= candidates[i];
path.removeLast();
}
}
}
40.组合总和II
40. 组合总和 II - 力扣(LeetCode)
本题要求数组中可以有重复数值,但是最后的结果中不能有重复的组合,所以中间过程需要去重,先把数组排序,进行数层去重,比如两个1相邻,第一个1遍历后,第二个1就可以不用遍历了,因为第一个1遍历的过程已经包含了第二个1遍历的结果
class Solution {
public List<List<Integer>> result = new ArrayList<>();
public List<Integer> path = new LinkedList<>();
boolean[] used;
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, 0);
return result;
}
public void backTracking(int[] candidates, int target, int sum, int startIndex) {
//这里没有return结束,因为candidates里有重复的值,后面可能还会有结果
if (sum == target) {
result.add(new ArrayList<>(path));
}
for (int i = startIndex; i < candidates.length; i++) {
//去重:used=true代表在树枝上有重复的值,不需要去重;used=false代表在数层上有重复的值,又是回溯产生的,需要去重
if (i > 0 && candidates[i] == candidates[i-1] && !used[i-1]) {
continue;
}
sum += candidates[i];
if (sum > target) {
break;
}
used[i] = true;
path.add(candidates[i]);
backTracking(candidates, target, sum, i+1);
used[i] = false;
sum -= candidates[i];
path.removeLast();
}
}
}
131.分割回文串
131. 分割回文串 - 力扣(LeetCode)
本题在判断分割的字符串是回文子串后,将其加入path中,并且将判断分割到最后是否合格的过程,放到for循环中
class Solution {
List<String> path = new LinkedList<>();
List<List<String>> result = new ArrayList<>();
public List<List<String>> partition(String s) {
backTracking(s, 0);
return result;
}
public void backTracking(String str, int startIndex) {
if (startIndex >= str.length()) {
result.add(new ArrayList<>(path));
return;
}
for (int i = startIndex; i < str.length(); i++) {
if (isPalindrome(str, startIndex, i)) {
String str1 = str.substring(startIndex, i + 1);
path.add(str1);
} else {
continue;
}
backTracking(str, i + 1);
path.removeLast();
}
}
// 判断是否是回文子串,左闭右闭区间
public boolean isPalindrome(String str, int start, int end) {
for (int i = start, j = end; i < j; i++, j--) {
if (str.charAt(i) != str.charAt(j)) {
return false;
}
}
return true;
}
}