39. 组合总和
本题是 集合里元素可以用无数次,那么和组合问题的差别 其实仅在于 startIndex上的控制
题目链接/文章讲解:代码随想录
视频讲解:带你学透回溯算法-组合总和(对应「leetcode」力扣题目:39.组合总和)| 回溯法精讲!_哔哩哔哩_bilibili
class Solution {
public List<List<Integer>> findCombinations(int[] candidates, int target) {
List<List<Integer>> results = new ArrayList<>();
Arrays.sort(candidates);
exploreCombinations(results, new ArrayList<>(), candidates, target, 0, 0);
return results;
}
private void exploreCombinations(List<List<Integer>> results, List<Integer> current, int[] candidates, int target, int currentSum, int startIndex) {
if (currentSum == target) {
results.add(new ArrayList<>(current));
return;
}
for (int i = startIndex; i < candidates.length; i++) {
if (currentSum + candidates[i] > target) break;
current.add(candidates[i]);
exploreCombinations(results, current, candidates, target, currentSum + candidates[i], i);
current.remove(current.size() - 1);
}
}
}
40.组合总和II
本题开始涉及到一个问题了:去重。
注意题目中给我们 集合是有重复元素的,那么求出来的 组合有可能重复,但题目要求不能有重复组合。
class Solution {
List<List<Integer>> combinations = new ArrayList<>();
LinkedList<Integer> currentPath = new LinkedList<>();
int runningSum = 0;
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
Arrays.sort(candidates);
backtrack(candidates, target, 0);
return combinations;
}
private void backtrack(int[] candidates, int remainingTarget, int startIndex) {
if (runningSum == remainingTarget) {
combinations.add(new ArrayList<>(currentPath));
return;
}
for (int i = startIndex; i < candidates.length && runningSum + candidates[i] <= remainingTarget; i++) {
// Skip duplicates in the same level
if (i > startIndex && candidates[i] == candidates[i - 1]) {
continue;
}
runningSum += candidates[i];
currentPath.add(candidates[i]);
backtrack(candidates, remainingTarget - candidates[i], i + 1);
runningSum -= candidates[i];
currentPath.removeLast();
}
}
}
题目链接/文章讲解:代码随想录
视频讲解:回溯算法中的去重,树层去重树枝去重,你弄清楚了没?| LeetCode:40.组合总和II_哔哩哔哩_bilibili
131.分割回文串
本题较难,大家先看视频来理解 分割问题,明天还会有一道分割问题,先打打基础。
class Solution {
List<List<String>> partitions = new ArrayList<>();
Deque<String> partitionPath = new LinkedList<>();
public List<List<String>> partition(String s) {
backtrack(s, 0);
return partitions;
}
private void backtrack(String s, int startIdx) {
if (startIdx >= s.length()) {
partitions.add(new ArrayList<>(partitionPath));
return;
}
for (int i = startIdx; i < s.length(); i++) {
if (isPalindrome(s, startIdx, i)) {
String substring = s.substring(startIdx, i + 1);
partitionPath.addLast(substring);
backtrack(s, i + 1);
partitionPath.removeLast();
}
}
}
private boolean isPalindrome(String s, int start, int end) {
while (start < end) {
if (s.charAt(start++) != s.charAt(end--)) {
return false;
}
}
return true;
}
}