39. 组合总和
题目链接:39. 组合总和
思路:
这道题的关键在于 candidates 中的元素可以复用多次,标准的组合问题通过下一层回溯从i + 1开始来保证不重复使用元素的,如果我想让每个元素被重复使用,我只要把 i + 1 改成 i 即可
class Solution {
LinkedList<Integer> track = new LinkedList<>();
List<List<Integer>> res = new LinkedList<>();
int sum;
public List<List<Integer>> combinationSum(int[] candidates, int target) {
backtrack(candidates, target, 0);
return res;
}
void backtrack(int[] candidates, int target, int start) {
if (sum == target) {
res.add(new LinkedList<>(track));
return;
}
if (sum > target) {
return;
}
for (int i = start; i < candidates.length; i++) {
track.add(candidates[i]);
sum += candidates[i];
backtrack(candidates, target, i);
track.removeLast();
sum -= candidates[i];
}
}
}
40. 组合总和 II
题目链接:40. 组合总和 II
思路:
我们需要进行剪枝,如果一个节点有多条值相同的树枝相邻,则只遍历第一条,剩下的都剪掉,不要去遍历。体现在代码上,需要先进行排序,让相同的元素靠在一起,如果发现 nums[i] == nums[i-1],则跳过。
class Solution {
LinkedList<Integer> track = new LinkedList<>();
List<List<Integer>> res = new LinkedList<>();
int sum = 0;
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
Arrays.sort(candidates);
backtrack(candidates, target, 0);
return res;
}
void backtrack(int[] candidates, int target, int start) {
if (sum == target) {
res.add(new LinkedList<>(track));
return;
}
if (sum > target) {
return;
}
for (int i = start; i < candidates.length; i++) {
if (i > start && candidates[i] == candidates[i - 1]) {
continue;
}
track.add(candidates[i]);
sum += candidates[i];
backtrack(candidates, target, i + 1);
track.removeLast();
sum -= candidates[i];
}
}
}
131. 分割回文串
题目链接:131. 分割回文串
思路:
难点在于如何在代码中实现字符串的切割线,其实startIndex就可以实现切割线的功能,[startIndex, i]就是分割出来的字符串。判断字串是不是回文串,如果不是,continue。
class Solution {
List<List<String>> res = new ArrayList<>();
LinkedList<String> track = new LinkedList<>();
public List<List<String>> partition(String s) {
backtrack(s, 0);
return res;
}
private void backtrack(String s, int startIndex) {
//如果起始位置大于s的大小,说明找到了一组分割方案
if (startIndex >= s.length()) {
res.add(new LinkedList(track));
return;
}
for (int i = startIndex; i < s.length(); i++) {
if (isPalindrome(s, startIndex, i)) {
String str = s.substring(startIndex, i + 1);
track.add(str);
} else {
continue;
}
backtrack(s, i + 1);
track.removeLast();
}
}
//判断是否是回文串
private boolean isPalindrome(String s, int startIndex, int end) {
for (int i = startIndex, j = end; i < j; i++, j--) {
if (s.charAt(i) != s.charAt(j)) {
return false;
}
}
return true;
}
}