LeetCode 39 组合总和
题目链接:39. 组合总和
【解题思路】
本题元素可以重复选取,因此剩余的集合就需要包括当前选取的元素。
【解题步骤】
-
主函数部分:
-
【全局变量】path一维数组用来存放单一节点
-
【全局变量】result二维数组用来存放结果集
-
调用递归函数,传入candidate,target,0,0
-
return result
-
-
递归函数部分:
-
1.确定参数和返回值:
-
返回值:
-
void
-
-
参数:
-
题目的数组candidate
-
目标值target
-
统计path里面元素的和的变量sum
-
startIndex标志开始遍历的起始位置
-
-
-
2.确定终止条件:
-
如果sum大于target
-
直接return
-
-
如果sum等于target
-
收集结果集
-
return
-
-
-
3.确定单层处理逻辑:
-
for循环遍历每一个candidate的数组元素
-
1)将当前遍历到的元素放入到路径集合path里
-
2)sum累加当前元素
-
3)递归,调用当前函数,传入:
-
数组candidate
-
目标值target
-
当前路径总和sum
-
本题我们可以重复选取元素,因此我们的遍历起始位置在本层是不变的,传入i
-
-
4)回溯:
-
sum将当前元素减掉
-
将当前元素从路径集合path里弹出
-
-
-
-
【代码部分】
java:
class Solution {
List<List<Integer>> result = new ArrayList<>();
List<Integer> path = new ArrayList<>();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
Arrays.sort(candidates);
backTracikng(candidates,target,0,0);
return result;
}
public void backTracikng(int[] candidates,int target,int sum, int startIndex){
if(sum == target){
result.add(new ArrayList<>(path));
return;
}
for(int i = startIndex; i< candidates.length; i++){
if(sum + candidates[i] > target) break;
path.add(candidates[i]);
sum+=candidates[i];
backTracikng(candidates,target,sum,i);
sum-= candidates[i];
path.remove(path.size() - 1);//移除最后一个元素
}
}
}
LeetCode 40 组合总和II
题目链接:40.组合总和II
【解题思路】
-
本题元素会有重复,需要进行去重操作
-
不能出现重复的组合,也不能出现重复的元素
-
可以在搜索过程中直接进行去重
-
“树层去重”
-
同一树层上重复元素不可以重复选取
-
树层去重需要对数组进行排序
-
用used判断树层元素是否重复
-
-
“树枝去重”
-
同一树枝上相同重复元素不可以重复选取
-
用candidates[i]是否等于candidates[i-1]判断树枝元素是否重复
-
-
【解题步骤】
-
主函数部分:
-
【全局变量】path一维数组用来存放单一节点
-
【全局变量】result二维数组用来存放结果集
-
【全局变量】布尔类型数组used用来记录同一树层上的元素是否使用过
-
将uesd数组里的元素用false填满
-
将数组进行排序
-
调用递归函数,传入candidate,target,0,0
-
return result
-
-
递归函数部分:
-
1.确定参数和返回值:
-
返回值:
-
void
-
-
参数:
-
题目的数组candidate
-
目标值target
-
统计path里面元素的和的变量sum
-
startIndex标志开始遍历的起始位置
-
-
-
2.确定终止条件:
-
如果sum大于target
-
直接return
-
-
如果sum等于target
-
收集结果集
-
return
-
-
-
3.确定单层处理逻辑:
-
for循环遍历每一个candidate的数组元素
-
判断元素是否重复
-
树枝元素重复:candidates[i]等于candidates[i-1]
-
树层元素重复:usde[i] == true
-
-
uesd[i] = true
-
将当前遍历到的元素放入到路径集合path里
-
sum累加当前元素
-
递归,调用当前函数,传入:
-
数组candidate
-
目标值target
-
当前路径总和sum
-
本题我们不可以重复选取元素,因此我们的遍历起始位置需要+1,传入i+1
-
-
回溯:
-
used[i] = false
-
sum将当前元素减掉
-
将当前元素从路径集合path里弹出
-
-
-
-
【代码部分】
java:
class Solution {
List<List<Integer>> result = new LinkedList<>();
List<Integer> path = new ArrayList<>();
boolean[] used;
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,0);
return result;
}
public void backTracking(int[] candidates, int target, int sum, int starIndex){
if(sum == target){
result.add(new ArrayList<>(path));
}
for(int i = starIndex ; 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,sum,i+1);
used[i] = false;
sum -= candidates[i];
path.remove(path.size() - 1);
}
}
}
LeetCode 131 分割回文串
题目链接:131. 分割回文串
【解题思路】
本题是一个分割问题,也可以看作一个树形结构,分割了一个字符之后,再从剩下的字符里进行分割。
【解题步骤】
-
主函数部分:
-
【全局变量】path一维数组用来存放单一的分割方案(其实就是收集路径的过程)
-
【全局变量】result二维数组用来存放符合条件的path
-
调用递归函数,传入字符串s,开始位置0
-
return result
-
-
递归函数部分:
-
1.确定参数和返回值:
-
返回值:
-
void
-
-
参数:
-
题目给出的字符串String s
-
startIndex标志开始遍历的起始位置
-
-
-
2.确定终止条件:
-
如果startIndex大于等于字符串s的长度,说明已经切割到结尾了
-
收集结果集
-
return
-
疑问:为什么直接收集结果集,不判断结果是否符合回文字符串的条件呢?
-
因为在单层搜索逻辑里已经有判断的逻辑了,如果当前不是回文,就不会进行下一次递归
-
-
-
-
3.确定单层处理逻辑:
-
for循环遍历字符串中的每一个字符
-
定义一个函数isPalindrome()判断当前切割的子串是否为回文子串,传入起始位置和终止位置
-
如果当前子串为回文子串,则将其加入path数组里
-
如果当前子串不是会为子串,直接跳到下一个i
-
-
递归,调用当前函数,传入:
-
字符串s
-
起始位置i+1
-
-
回溯:
-
将当前字符从path里弹出
-
-
-
-
【代码部分】
java:
class Solution {
List<List<String>> result = new ArrayList<>();
Deque<String> path = new LinkedList<>();
public List<List<String>> partition(String s) {
backTracking(s,0);
return result;
}
public void backTracking(String s, int starIndex){
if(starIndex >= s.length()){
result.add(new ArrayList(path));
return;
}
for (int i = starIndex; i <s.length() ; i++) {
if(isPalindrome(s,starIndex,i)){
String str = s.substring(starIndex,i+1);
path.addLast(str);
}else{
continue;
}
backTracking(s,i+1);
path.removeLast();
}
}
public 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;
}
}