当前位置: 首页 > article >正文

代码随想录算法训练营第27天| 39. 组合总和、40.组合总和II、131.分割回文串

39. 组合总和

完成

思路:

本题中有一个特殊的条件:同一个数字可以无限制重复被选取。
因此在递归时,startIndex应该是i,而不是i+1

代码

class Solution {
    public List<List<Integer>> res = new ArrayList<>();
    public List<Integer> path = new ArrayList<>();
    public int sum = 0;
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        backtracking(candidates, target, 0);
        return res;
    }
    public void backtracking(int[] candidates, int target, int startIndex){
        if(sum == target){
            res.add(new ArrayList<>(path));
            return;
        }
        if(sum > target) return;
        for (int i = startIndex; i < candidates.length; i++) {
            path.add(candidates[i]);
            sum+=candidates[i];
            backtracking(candidates, target, i);
            sum-=candidates[i];
            path.removeLast();
        }
    }
}

再考虑如何剪枝,在调试测试用例[2,3,6,7]时发现,如果集合是递增的,前面的元素如果相加超出范围,那么也就无需考虑后面的元素了,必定也超范围。

因此可以先给集合排序。

class Solution {
    public List<List<Integer>> res = new ArrayList<>();
    public List<Integer> path = new ArrayList<>();
    public int sum = 0;
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
    	// 数组排序
        Arrays.sort(candidates);
        backtracking(candidates, target, 0);
        return res;
    }
    public void backtracking(int[] candidates, int target, int startIndex){
        if(sum == target){
            res.add(new ArrayList<>(path));
            return;
        }
        for (int i = startIndex; i < candidates.length; i++) {
        	// 直接跳出循环,第一个 > target的元素及其后面的元素都不遍历
            if(sum+candidates[i] > target) break;
            path.add(candidates[i]);
            sum+=candidates[i];
            backtracking(candidates, target, i);
            sum-=candidates[i];
            path.removeLast();
        }
    }
}

40.组合总和II

完成

思路:

题目要求解集不能包含重复的组合,但是候选数组中如果有重复元素,不加处理就会必定产生重复集合。

一开始的想法是先用set去重,再返回List,会超时。

因此只能在遍历时去重,组合问题可以抽象为树形结构,那么去重在这个树形结构上是有两个维度的,一个维度是同一树枝上去重,一个维度是同一树层上去重
本题应该是在同一树层上去重,同一树枝上无需去重。

代码

class Solution {
    public List<List<Integer>> res = new ArrayList<>();
    public List<Integer> path = new ArrayList<>();
    public int sum = 0;
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        Arrays.sort(candidates);
        backtracking(candidates, target, 0);
        return res;
    }
    public void backtracking(int[] candidates, int target, int startIndex){
        if(sum == target){
            res.add(new ArrayList<>(path));
            return;
        }
        if(sum > target) return;
        for (int i = startIndex; i < candidates.length; i++) {
            // 同一树层去重,注意是i>startIndex,如果是i>0,树层和树枝都会去重
            if(i>startIndex && candidates[i] == candidates[i-1]) continue;
            
            path.add(candidates[i]);
            sum+=candidates[i];
            backtracking(candidates, target, i+1);
            sum-=candidates[i];
            path.removeLast();
        }
    }
}

131.分割回文串

完成

思路:

注意分割方法
在这里插入图片描述

代码

class Solution {
    //判断是否是回文串
    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;
    }

    public List<List<String>> res = new ArrayList<>();
    public Deque<String> path = new LinkedList<>();

    public List<List<String>> partition(String s) {
        backtracking(s, 0);
        return res;
    }

     private void backtracking(String s, int startIndex) {
        //如果起始位置大于s的大小,说明找到了一组分割方案
        if (startIndex >= s.length()) {
            res.add(new ArrayList(path));
            return;
        }
        for (int i = startIndex; i < s.length(); i++) {
            //如果是回文子串,则记录
            if (isPalindrome(s, startIndex, i)) {
                String str = s.substring(startIndex, i + 1);
                path.addLast(str);
            } else {
                continue;
            }
            //起始位置后移,保证不重复
            backtracking(s, i + 1);
            path.removeLast();
        }
    }
}

http://www.kler.cn/a/228650.html

相关文章:

  • 教师培训内容有哪些方面 本体知识和能力要求
  • 19.HarmonyOS App(JAVA)依赖布局DependentLayout使用方法
  • 关于v8垃圾回收机制以及与其相关联的知识点--还没整理版本
  • 云数据库RDS云监控
  • QT自用,勿点
  • EMNLP 2023精选:Text-to-SQL任务的前沿进展(上篇)——正会论文解读
  • 免重启解决docker No chain/target/match by that name 免重启解决方案
  • STM32F407移植OpenHarmony笔记7
  • [经验] 月字旁一个卢念什么 #职场发展#媒体#微信
  • 【开源精选导航】GitHub-Chinese-Top-Charts:一榜在手,优质中文项目轻松找寻
  • 通过Navicat for MySQL排查sql语句错误
  • 问题:下列哪些属于历史文化资源的特征( ). #学习方法#学习方法
  • linux 05重定向和管道管理
  • 如何使用VS Code编写小游戏并实现公网游玩本地游戏【内网穿透】
  • vue-3d-loader
  • Leetcode 3030. Find the Grid of Region Average
  • MySQL分区的优缺点
  • 哪些骨传导蓝牙立体声耳机好?骨传导蓝牙立体声耳机高性价比推荐
  • 使用代理IP有风险吗?如何安全使用代理IP?
  • vue 下载二进制文件