1. LeetCode 39. 组合总和
题目链接:https://leetcode.cn/problems/combination-sum/description/
文章链接:https://programmercarl.com/0039.组合总和.html
视频链接:https://www.bilibili.com/video/BV1KT4y1M7HJ
思路:
本题和77.组合 (opens new window)、216.组合总和III (opens new window)有两点不同:
1.组合没有数量要求;
2.元素可无限重复选取。
无数量要求,则不能根据列表长度进行终止,需要根据sum>target进行终止;
可重复取,则递归时不用startIndex加一。
解法:
class Solution {
List<List<Integer>> res = new ArrayList<>();
List<Integer> list = new ArrayList<>();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
if (candidates.length == 0) {
return res;
}
find(candidates,target,0,0);
return res;
}
public void find (int[] candidates,int target,int sum,int startIndex) {
if (sum == target) {
res.add(new ArrayList(list));
return;
} else if (sum > target) {
return;
}
for (int i=startIndex;i<candidates.length;i++) {
// 处理当前节点
list.add(candidates[i]);
sum += candidates[i];
// 递归
find(candidates,target,sum,i);
// 撤销当前节点
list.removeLast();
sum -= candidates[i];
}
}
}
2. LeetCode 40.组合总和II
题目链接:https://leetcode.cn/problems/combination-sum-ii/description/
文章链接:https://programmercarl.com/0040.组合总和II.html
视频链接:https://www.bilibili.com/video/BV12V4y1V73A
思路:
本题同样是求组合总和,但就是因为其数组candidates有重复元素,而要求不能有重复的组合,所以相对于39.组合总和 (opens new window),需要组合去重。
解法:
class Solution {
List<List<Integer>> res = new ArrayList<>();
List<Integer> list = new ArrayList<>();
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
if (candidates == null || candidates.length == 0) {
return res;
}
Arrays.sort(candidates);
find(candidates,target,0,0);
return res;
}
public void find(int[] candidates,int target,int sum,int startIndex) {
if (sum > target) {
return;
}
if (sum == target) {
res.add(new ArrayList(list));
return;
}
for (int i=startIndex;i<candidates.length;i++) {
// 当前层去重
if (i>startIndex) {
if (candidates[i] == candidates[i-1]) {
continue;
}
}
// 处理当前节点
list.add(candidates[i]);
sum+=candidates[i];
// 递归
find(candidates,target,sum,i+1);
// 撤销当前节点 回溯
list.removeLast();
sum-=candidates[i];
}
}
}
3. LeetCode 131.分割回文串
题目链接:https://leetcode.cn/problems/palindrome-partitioning/description/
文章链接:https://programmercarl.com/0131.分割回文串.html
视频链接:https://www.bilibili.com/video/BV1c54y1e7k6
思路:
与组合类似,不过组合是每层选出一个数值,而分割是每层选出多个相邻数值组成的字段。
注意:当前层的分割线是下一层的起点。
解法:
class Solution {
List<List<String>> res = new ArrayList<>();
List<String> list = new ArrayList<>();
public List<List<String>> partition(String s) {
if (s == null || s.length() == 0) {
return res;
}
find(s,0);
return res;
}
public void find(String s,int startIndex) {
// 终止条件
if (startIndex == s.length()) {
res.add(new ArrayList(list));
return;
}
// 遍历单层
for (int i=startIndex;i<s.length();i++) {
// 判断是否是回文串
if (isPalindrome(s.substring(startIndex,i+1))){// i+1是分割线
String subStr = s.substring(startIndex,i+1);
// 处理当前节点
list.add(subStr);
// 递归
find(s,i+1);
// 撤销当前节点
list.removeLast();
} else {
continue;
}
}
}
/**
判断是否是回文串
*/
public boolean isPalindrome(String sub) {
for (int i=0,j=sub.length()-1;i<j;i++,j--) {
if (sub.charAt(i) != sub.charAt(j)) {
return false;
}
}
return true;
}
}