代码随想录刷题|Day20(组合总数,组合总数2、分割回文串)

回溯算法 Part02

组合总数

力扣题目链接
代码随想录链接
视频讲解
题目描述: 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。

candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。

对于给定的输入,保证和为 target 的不同组合数少于 150 个。

思路,本题的解法和part01的组合总和3的思路差别不大,其解树如下:

唯一的区别在于本题目之中的元素是可以重复选取的,因此,在递归传递参数的时候,我们应该传递i而不是i+1;

回溯法

具体代码如下:

java 复制代码
class Solution {
    int sum = 0;
    List<Integer> path = new ArrayList<>();
    List<List<Integer>> result = new ArrayList<>(); 
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        backTracking(candidates,target,0);
        return result;
    }
    private void backTracking(int[] candidates , int target , int startIndex){
        // 剪枝操作
        if(sum > target) return ;
        if(startIndex > candidates.length) return ;
        // 满足条件的情况存储
        if(sum == target){
            result.add(new ArrayList<>(path));
            return ;
        }

        for(int i = startIndex ; i < candidates.length ; i++){
            sum += candidates[i];
            path.add(candidates[i]);
            // 递归
            backTracking(candidates,target,i);
            // 回溯
            sum -= candidates[i];
            path.removeLast();
        }
    }
}

组合总数2

力扣题目链接
代码随想录链接
视频讲解
题目描述: 给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的每个数字在每个组合中只能使用 一次 。

注意:解集不能包含重复的组合。

思路:因为给的candidates 之中包含重复的元素,所以可能造成解集之中也包含同样的输出,但题目之中要求解集不能包含重复的组合。本题的解树为:

回溯法

思路:

java 复制代码
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) return ;
    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();
    }
  }
}

回溯法(我的解决)

使用contains判断当前的结果path是否存在于result之中,不在则加入(会出现一些例子执行时间超出限制)

代码如下:

java 复制代码
class Solution {
    int sum = 0 ;
    List<Integer> path = new ArrayList<>();
    List<List<Integer>> result = new ArrayList<>();
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        Arrays.sort(candidates);
        backTracking(candidates,target,0);
        return result;
        
    }
    private void backTracking(int[] candidates , int target , int startIndex){
        if(sum > target) return ;

        if(sum == target && !result.contains(path)){
            result.add(new ArrayList<>(path));
            return ;
        }

        for(int i = startIndex ; i < candidates.length ; i++){
            sum += candidates[i];
            path.add(candidates[i]);
            backTracking(candidates,target,i + 1);
            sum -= candidates[i];
            path.remove(path.size() - 1);
        }

    }

}

分割回文串 (待补充)

力扣题目链接
代码随想录链接
视频讲解
题目描述:

回溯法

代码如下:

java 复制代码
class Solution {
    //保持前几题一贯的格式, initialization
    List<List<String>> res = new ArrayList<>();
    List<String> cur = new ArrayList<>();
    public List<List<String>> partition(String s) {
        backtracking(s, 0, new StringBuilder());
        return res;
    }
    private void backtracking(String s, int start, StringBuilder sb){
        //因为是起始位置一个一个加的,所以结束时start一定等于s.length,因为进入backtracking时一定末尾也是回文,所以cur是满足条件的
        if (start == s.length()){
            //注意创建一个新的copy
            res.add(new ArrayList<>(cur));
            return;
        }
        //像前两题一样从前往后搜索,如果发现回文,进入backtracking,起始位置后移一位,循环结束照例移除cur的末位
        for (int i = start; i < s.length(); i++){
            sb.append(s.charAt(i));
            if (check(sb)){
                cur.add(sb.toString());
                backtracking(s, i + 1, new StringBuilder());
                cur.remove(cur.size() -1 );
            }
        }
    }

    //helper method, 检查是否是回文
    private boolean check(StringBuilder sb){
        for (int i = 0; i < sb.length()/ 2; i++){
            if (sb.charAt(i) != sb.charAt(sb.length() - 1 - i)){return false;}
        }
        return true;
    }
}

相关推荐
binnnngo1 小时前
Minmax 算法与 Alpha-Beta 剪枝小教学
算法·机器学习·剪枝
এ᭄画画的北北2 小时前
力扣-287.寻找重复数
算法·leetcode
一只小青团6 小时前
Python之面向对象和类
java·开发语言
qq_529835356 小时前
ThreadLocal内存泄漏 强引用vs弱引用
java·开发语言·jvm
落笔画忧愁e6 小时前
扣子Coze飞书多维表插件添加数据记录
java·服务器·飞书
秋千码途8 小时前
小架构step系列08:logback.xml的配置
xml·java·logback
飞翔的佩奇8 小时前
Java项目:基于SSM框架实现的旅游协会管理系统【ssm+B/S架构+源码+数据库+毕业论文】
java·数据库·mysql·毕业设计·ssm·旅游·jsp
时来天地皆同力.9 小时前
Java面试基础:概念
java·开发语言·jvm
找不到、了9 小时前
Spring的Bean原型模式下的使用
java·spring·原型模式
阿华的代码王国10 小时前
【Android】搭配安卓环境及设备连接
android·java