39.组合总和
讲解链接:代码随想录-39.组合总和
这道题因为里面的数字可以重复使用,所以在下一层递归的时候,i 不用 +1。
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> result = new ArrayList<>();
Arrays.sort(candidates);
backtracking(candidates, target, 0, new ArrayList<>(), result);
return result;
}
void backtracking(int[] candidates, int target, int startIndex, List<Integer> paths, List<List<Integer>> result) {
int sum = 0;
for (int i = 0; i < paths.size(); i++) {
sum += paths.get(i);
}
if (sum >= target) {
if (sum == target) {
result.add(new ArrayList<>(paths));
}
return;
}
for (int i = startIndex; i < candidates.length && sum + candidates[i] <= target; i++) {
paths.add(candidates[i]);
backtracking(candidates, target, i, paths, result);
paths.remove(paths.size() - 1);
}
}
40.组合总和 II
讲解链接:代码随想录-40.组合总和 II
candidates 中的每个数字在每个组合中只能使用 一次 。
注意:解集不能包含重复的组合。
所以,这道题首先也要对参数进行排序,然后在处理路径的时候需要判断,如果当前元素跟前一个元素相同,那么就跳过,否则会在出现相同的组合。
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
Arrays.sort(candidates);
List<List<Integer>> results = new ArrayList<>();
backtracking(candidates, target, 0, new ArrayList<>(), results);
return results;
}
void backtracking(int[] candidates, int target, int startIndex, List<Integer> paths, List<List<Integer>> result) {
int sum = 0;
for (int i = 0; i < paths.size(); i++) {
sum += paths.get(i);
}
if (sum >= target) {
if (sum == target) {
result.add(new ArrayList<>(paths));
}
return;
}
for (int i = startIndex; i < candidates.length; i++) {
if (sum + candidates[i] > target) {
break;
}
// 相同字符就跳过
if (i > startIndex && candidates[i - 1] == candidates[i]) {
continue;
}
paths.add(candidates[i]);
backtracking(candidates, target, i + 1, paths, result);
paths.remove(paths.size() - 1);
}
}
131.分割回文串
讲解链接:代码随想录-131.分割回文串
看图好理解,重点在每次遍历后判断一下分割的子字符是否是回文字符串,是的话就添加到路径组合中,因为同一个元素不能重复使用,所以在递归的时候需要 +1。
public List<List<String>> partition(String s) {
List<List<String>> results = new ArrayList<>();
backtracking(s, 0, new ArrayList<>(), results);
return results;
}
void backtracking(String s, Integer startIndex, List<String> paths, List<List<String>> results) {
if (startIndex >= s.length()) {
results.add(new ArrayList<>(paths));
return;
}
for (int i = startIndex; i < s.length(); i++) {
if (isPalindrome(s, startIndex, i)) {
String sub = s.substring(startIndex, i + 1);
paths.add(sub);
} else {
continue;
}
backtracking(s, i + 1, paths, results);
paths.remove(paths.size() - 1);
}
}
boolean isPalindrome(String s, Integer leftIndex, Integer rightIndex) {
while (leftIndex < rightIndex) {
if (s.charAt(leftIndex) != s.charAt(rightIndex)) {
return false;
}
leftIndex++;
rightIndex--;
}
return true;
}