[刷题记录Day 27]Leetcode组合之回溯算法

No.1

题目

组合总和

思路

  • 回溯法
  • 不限制数字使用次数,如何处理?
    • 横向遍历树时,还需要使用startIndex,以避免对同一个组合重复多次搜索
    • 但是在递归下一层时,参数中不需要startIndex + 1,表示允许从startIndex开始搜索
  • 数字集中出现0会怎么样?
    • 无限含不同数量0的组合
  • 考虑给空的candidates数组,怎么处理

递归分析

  1. 全局变量pathresult
  2. 返回值:空,参数:可用数字集,targetstartIndex
  3. 终止条件
    1. 路径累计值和target相等,存储结果到result,返回
    2. 路径累计值已经大于target,返回(剪枝)
    3. 路径走到尽头(耗尽所有可用数字),不存在,数字不限制使用次数
  4. 单层递归逻辑
    1. 处理当前节点
    2. 递归进入下一层搜索
    3. 回溯,抛出当前节点

代码

private List<Integer> path;
private List<List<Integer>> result;
public void combineHelper(int[] candidates, int target, int startIndex) {
if (target == 0) {
result.add(new ArrayList<>(path));
return;
} else if (target < 0) { // 已经超过了target,没有必要继续搜索这一分支
return;
}
for (int i = startIndex; i < candidates.length; i++) {
path.add(candidates[i]);
target -= candidates[i];
combineHelper(candidates, target, i); // 不限制单个数字的使用次数,就体现在这里
target += candidates[i];
path.remove(path.size() - 1);
}
}
public List<List<Integer>> combinationSum(int[] candidates, int target) {
path = new ArrayList<>();
result = new ArrayList<>();
if (candidates.length == 0)
return result;
combineHelper(candidates, target, 0);
return result;
}

No.2

题目

组合总和 II

思路

  • 回溯法,大体和No.1类似
  • 这道题目和组合总和如下区别
    • 本题数组candidates的元素是有重复的,而组合总和无重复元素的数组candidates
  • 新要求:解集不能包含重复的组合,怎么处理?
    • 先对candidates排序,然后在横向遍历时,判断与path末尾的数字是否相同,相同则continue,跳过这个数字

递归分析

  1. 全局变量pathresult
  2. 返回值:空,参数:可用数字集,targetstartIndex
  3. 终止条件
    1. 路径累计值和target相等,存储结果到result,返回
    2. 路径累计值已经大于target,返回(剪枝)
    3. 路径走到尽头(耗尽所有可用数字),返回(剪枝)
  4. 单层递归逻辑
    1. 处理当前节点
    2. 递归进入下一层搜索
    3. 回溯,抛出当前节点

代码

private List<Integer> path;
private List<List<Integer>> result;
public void combineHelper(int[] candidates, int target, int startIndex) {
if (target == 0) {
result.add(new ArrayList<>(path));
return;
} else if (target < 0) {
return;
}
if (target > 0 && startIndex >= candidates.length)
return;
for (int i = startIndex; i < candidates.length; i++) {
int num = candidates[i];
// 在这里去除重复结果
if (i > startIndex && num == candidates[i - 1])
continue;
path.add(num);
target -= num;
combineHelper(candidates, target, i + 1); // 和不限制元素使用次数情况不同
target += num;
path.remove(path.size() - 1);
}
}
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
path = new ArrayList<>();
result = new ArrayList<>();
if (candidates.length == 0)
return result;
// 先对candidates排序
Arrays.sort(candidates);
combineHelper(candidates, target, 0);
return result;
}

No.3

题目

分割回文串

思路

  • 先写一个判断回文串的函数
  • 回溯法
  • 这是切割问题,类似组合问题

递归分析

  1. 全局变量pathresult
  2. 返回值:空,参数:原生字符串,splitIndex
  3. 终止条件
    1. 字符串用光了,存储结果,返回
  4. 单层递归逻辑
    1. 处理当前节点
    2. 割下来的字符串是回文串,进入下一层递归
    3. 回溯,抛出当前节点

代码

public boolean judgeReversal(String s) {
int len = s.length();
// left, right时刻同步变化,所以写在for条件里面
for (int left = 0, right = len - 1;left <= right ; left++, right--) {
if (s.charAt(left) != s.charAt(right))
return false;
}
return true;
}
private List<String> path;
private List<List<String>> result;
public void partHelper(String s, int startIndex) { // before, not included
if (startIndex >= s.length()) {
result.add(new ArrayList<>(path));
return;
}
for (int i = startIndex; i < s.length(); i++) {
String subStr = s.substring(startIndex, i + 1);
path.add(subStr);
if (judgeReversal(subStr))
partHelper(s, i + 1);
path.remove(path.size() - 1);
}
}
public List<List<String>> partition(String s) {
path = new ArrayList<>();
result = new ArrayList<>();
partHelper(s, 0);
return result;
}
posted @   喜欢毛绒绒的番茄子  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
点击右上角即可分享
微信分享提示