39. 组合总和
- 题目链接:39. 组合总和
- 解题思路&主要难点:本题和之前几个组合问题不一样的地方有两个,一个是组合中的元素可以重复使用,另一个是每次输出结果的长度不固定。其他思路还是一样,建立树结构,每次从整个序列中进行选取,加入后比较当前总和是否与target相同,若相同则返回,小于则继续从整个序列中选取,大于则回溯。
- 解题时间:20+5
- 代码:
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> res=new ArrayList<>();
Arrays.sort(candidates);
back(res,new ArrayList<>(),candidates,target,0,0);
return res;
}
public void back(List<List<Integer>> res,List<Integer> path,int[] candidates,int target,int sum, int idx){
if(sum==target){
res.add(new ArrayList<>(path));
return;
}
for(int i=idx;i<candidates.length;i++){
if(sum+candidates[i]>target){
break;
}
path.add(candidates[i]);
back(res,path,candidates,target,sum+candidates[i],i);
path.remove(path.size()-1);
}
}
}
40. 组合总和 II
- 题目链接:40. 组合总和 II
- 解题思路:和上面题目要求基本一样,加了一条限制要求每次候选集合中的元素不能重复,但是候选集里是有可能有重复元素的
- 主要难点:去重比较难理解(二刷需要重新看)
- 解题时间:30+5
- 代码:
class Solution {
LinkedList<Integer> path = new LinkedList<>();
List<List<Integer>> ans = new ArrayList<>();
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 ans;
}
private void backTracking(int[] candidates, int target, int startIndex) {
if (sum == target) {
ans.add(new ArrayList(path));
}
for (int i = startIndex; i < candidates.length; i++) {
if (sum + candidates[i] > target) {
break;
}
if (i > 0 && candidates[i] == candidates[i - 1] && !used[i - 1]) {
continue;
}
used[i] = true;
sum += candidates[i];
path.add(candidates[i]);
backTracking(candidates, target, i + 1);
used[i] = false;
sum -= candidates[i];
path.removeLast();
}
}
}
131. 分割回文串
- 题目链接:131. 分割回文串
- 解题思路:切割问题和组合问题其实差不多,一个是从剩下的序列里选一部分切除,一个是从集合中选一个组合,也可以抽象成树结构。
- 主要难点:切割问题抽象成树形结构
- 解题时间:20+5
- 代码:
class Solution {
List<List<String>> lists = new ArrayList<>();
Deque<String> deque = new LinkedList<>();
public List<List<String>> partition(String s) {
backTracking(s, 0);
return lists;
}
private void backTracking(String s, int startIndex) {
if (startIndex >= s.length()) {
lists.add(new ArrayList(deque));
return;
}
for (int i = startIndex; i < s.length(); i++) {
if (isPalindrome(s, startIndex, i)) {
String str = s.substring(startIndex, i + 1);
deque.addLast(str);
} else {
continue;
}
backTracking(s, i + 1);
deque.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;
}
}