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

news2024/11/14 15:38:46

今日内容

  • leetcode. 39 组合总和
  • leetcode. 40 组合总和Ⅱ
  • leetcode. 131 分割回文串

Leetcode. 39 组合总和

文章链接:代码随想录 (programmercarl.com)

题目链接:39. 组合总和 - 力扣(LeetCode)

本题不太一样的是可以对同一个数字进行无限制的重复选取,因此进行递归时,startIndex应该不变,从而保证对同个元素进行重复选取。

题目中还说:如果至少一个数字的被选数量不同,则两种组合是不同的。因为题目中给出的candidates数组有序,按照回溯的正常流程,某个数字的被选择次数按照流程走的话,肯定会是不同的。

基于回溯模板和抽象树形结构,我们写出如下代码:

class Solution {
    List<Integer> elem = new LinkedList<>();
    List<List<Integer>> result = new LinkedList<>();
    int sum = 0;
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        backtracking(candidates, target, 0);
        return result;
    }
    public void backtracking(int[] candidates, int target, int startIndex){
        if (sum > target){
            return;
        }
        if (sum == target){
            result.add(new LinkedList<>(elem));
            return;
        }
        for (int i = startIndex; i < candidates.length; i++){
            sum += candidates[i];
            elem.add(candidates[i]);
            backtracking(candidates, target, i); // 注意不是 i + 1 了
            sum -= candidates[i];
            elem.remove(elem.size() - 1);
        }

    }
}
  • 时间复杂度:O(n * 2 ^ n)
  • 空间复杂度:O(target)

Leetcode. 40 组合总和Ⅱ

文章链接:代码随想录 (programmercarl.com)

题目链接:40. 组合总和 II - 力扣(LeetCode)

本题基于 组合总和 这道题目,加了个 去重 的限制。现在每个数字在每个组合中只能使用一次。

实际上如果按照最普通的回溯模板来写这道题,最后会发现题目中所说的重复和前面哈希法专题中的 15. 三数之和 - 力扣(LeetCode)比较类似,所以去重思路也可以向 三数之和 看齐,即先将数组进行排序,把第一个元素按照正常流程进行处理,若后一个元素和其前一个元素一样,则跳过该元素

注意,这里的排序非常重要!没有排序的话,就无法使用这样的去重思路。

根据思路、回溯模板和抽象树形图,写出如下代码:

class Solution {
    List<Integer> elem = new LinkedList<>();
    List<List<Integer>> result = new LinkedList<>();
    int sum = 0;
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        Arrays.sort(candidates);
        backtracking(candidates, target, 0);
        return result;
    }
    public void backtracking(int[] candidates, int target, int startIndex){
        if (sum == target){
            result.add(new LinkedList<>(elem));
            return;
        }
        // 加入了剪枝操作
        for (int i = startIndex; i < candidates.length && sum + candidates[i] <= target; i++){
            // 剔除同一层中用过的元素
            if (i > startIndex && candidates[i] == candidates[i - 1]){
                continue;
            }
            sum += candidates[i];
            elem.add(candidates[i]);
            backtracking(candidates, target, i + 1);
            sum -= candidates[i];
            elem.remove(elem.size() - 1);
        }
    }
}
  • 时间复杂度:O(n * 2 ^ n)
  • 空间复杂度:O(n)

Leetcode. 131 分割回文串

文章链接:代码随想录 (programmercarl.com)

题目链接:131. 分割回文串 - 力扣(LeetCode)

前面做的都是回溯问题中的组合问题,本题就是回溯问题中的另一类:分割问题。 

实际上分割问题与组合问题非常类似,比如对于字符串 abcdef:

  • 组合问题:选取 a 之后,在 bcdef 中再去选取第二个。选取 b 之后再去 cdef 中 选取第三个……
  • 分割问题:分割 a 之后,在 bcdef 中再去分割第二个。分割 b 之后再去 cdef 中 分割第三个……

因此将本题的分割问题抽象为树形结构图后,结果如下:

从抽象树形图中可以看出,分割问题与组合问题的回溯搜索过程基本无异。

基于此写出代码:

class Solution {
    List<String> elem = new LinkedList<>();
    List<List<String>> result = new LinkedList<>();

    public List<List<String>> partition(String s) {
        backtracking(s, 0);
        return result;
    }
    public void backtracking(String s, int startIndex){
        /*
        这里的startIndex表示分割线,
        分割线如果超过了字符串长度,则说明已经到头,可以停止了
        */
        if (startIndex >= s.length()){
            result.add(new LinkedList<>(elem));
            return;
        }
        for (int i = startIndex; i < s.length(); i++){
            if (isPalindrome(s, startIndex, i)){
                String str = s.substring(startIndex, i + 1);
                elem.add(str);
            } else {
                continue;
            }
            backtracking(s, i + 1);
            elem.remove(elem.size() - 1);
        }
    }
    // 判断字符串是否回文
    public boolean isPalindrome(String s, int start, int end){
        while (start < end){
            if (s.charAt(start) == s.charAt(end)){
                start++;
                end--;
            } else {
                return false;
            }
        }
        return true;
    }
}
  • 时间复杂度:O(n * 2 ^ n)
  • 空间复杂度:O(n ^ 2)

总结

组合问题中,要根据题目的意思确定startIndex的位置。

回溯法中的去重思想,可以套用哈希法中的 三数之和 问题的去重思想。

分割问题和组合问题非常类似,基本无异。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2113918.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

自己实现一个分布式锁

我的博客大纲 我的后端学习大纲 1.setnx命令&#xff1a; 2.基于Redis实现分布式锁&#xff1a; 2.1.基本实现&#xff1a; 借助于redis中的命令setnx(key, value)&#xff0c;key不存在就新增&#xff0c;存在就什么都不做。同时有多个客户端发送setnx命令&#xff0c;只有一…

20240902-VSCode-1.19.1-部署vcpkg-win10-22h2

20240902-VSCode-1.19.1-部署vcpkg-win10-22h2 软件环境 标签:C++ VSCode mingw gcc13 vcpkg cmake分栏:C++操作系统:Windows10 x64 22h2一、安装VScode-1.19.1 请参考另一篇文章《20240717-VSCode-1.91.1-部署gcc13-C++23-win10-22h2》。 二、安装cmake 本文流程需要安…

【微处理器系统原理与应用设计第八讲】程序设计的开发框架包括编程语言、程序的基本要素、汇编程序结构、集成开发环境

一、编程语言 从处理器的角度看&#xff1a;一个指令只是一个操作&#xff0c;那么执行多条指令构成的程序就是完成一个完整功能的操作。 从程序执行的角度看&#xff1a;处理器读取指令后译码执行&#xff0c;完成所有操作。 从程序设计的角度看&#xff1a;用指令来描述所…

尽快更新!Zyxel 路由器曝出 OS 命令注入漏洞,影响多个版本

近日&#xff0c;Zyxel 发布安全更新&#xff0c;以解决影响其多款商用路由器的关键漏洞&#xff0c;该漏洞可能允许未经认证的攻击者执行操作系统命令注入。 该漏洞被追踪为 CVE-2024-7261&#xff0c;CVSS v3 得分为 9.8&#xff0c;是一个输入验证故障&#xff0c;由用户提…

“榆”您相约|遨游矿用煤安防爆手机助力煤矿作业安全增效

金秋九月结硕果&#xff0c;丹桂飘香迎盛会。2024年9月13日至15日&#xff0c;第十八届榆林国际煤炭暨高端能源化工产业博览会&#xff08;以下简称“榆林国际煤博会”&#xff09;即将在榆林会展中心盛大启幕。本次博览会以“能源新时代&#xff0c;低碳新榆林”为主题&#x…

SAP学习笔记 - 开发03 - CDSView开发环境搭建,Eclipse中连接SAP,CDSView创建

上一章讲了BTP的账号创建&#xff0c;环境搭建等内容。 SAP学习笔记 - 开发02 - BTP实操流程&#xff08;账号注册&#xff0c;BTP控制台&#xff0c;BTP集成开发环境搭建&#xff09;-CSDN博客 本章继续讲SAP开发。 - CDSView 的开发环境&#xff08;Eclipse&#xff09;搭建…

世界公认十大护眼灯数据出炉!一文看懂孩子用的台灯哪个牌子好

近年来&#xff0c;随着科技的迅猛发展&#xff0c;诸如智能手机、电脑等电子设备在工作、学习及娱乐中的应用日益广泛&#xff0c;人们对这些设备的依赖程度也随之加深。然而&#xff0c;长时间面对屏幕不可避免地给眼睛带来伤害&#xff0c;如眼疲劳、干燥甚至近视等问题。因…

线程池概念介绍

一、初始化线程的四种方式 1.继承Thread 2.实现Runnable 3.实现Callable接口FutureTask 4.线程池:两种主要初始化方式Executors.newFixedThreadPool()或new ThreadPoolExecutor() 方式1和方式2:主进程无法获取线程的运算结果。 方式3:主进程可以获取运算结果&#xff0c;但是…

MMO地图传送

本篇由以下四个点讲解&#xff1a; 创建传送点 传送点配置 编辑器扩展&#xff1a;传送点数据生成 传送协议与实现 创建传送点 建碰撞器触发 //位置归零 建一个传送门cube放到要传送的位置&#xff08;这个teleporter1是传出的区域 这是从另一张地图传入时的传送门 创建一…

mysql笔记—基础

1.SQL语句 DDL&#xff08;数据库对象操作&#xff09;、DML&#xff08;增删改&#xff09;、DQL&#xff08;查询&#xff09;、DCL&#xff08;用户和权限操作&#xff09; 2.DDL&#xff1a; 1.数据库操作&#xff1a; show databases; create database []; use []; sele…

网络工程师学习笔记——无线通信网

移动通信 从1G到3G都是针对语音通话设计的&#xff0c;只有4&#xff27;才可以与Internet衔接 1978年美国贝尔实验室开发了高级移动电话系统&#xff08;AMPS&#xff09;&#xff0c;可以随时随地的进行通信&#xff0c;采用蜂窝技术解决了公用通信系统所面临的大容量要求和…

初识Linux · 进度条

目录 前言&#xff1a; 1 缓冲区和回车换行 2 进度条 前言&#xff1a; 我们目前学习了些许知识&#xff0c;已经足够支持我们写一个非常非常小的项目了&#xff0c;即进度条&#xff0c;相信大家都有过下载游戏&#xff0c;等待游戏更新完成的时候&#xff0c;那么此时就有…

电器维修系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;客服聊天管理&#xff0c;基础数据管理&#xff0c;公告管理&#xff0c;新闻信息管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;新闻信息&#xff0c;我的 开发系…

站长工具 API 接口,助力网站管理新高度

站长工具是一款非常实用的网站管理工具&#xff0c;通过其提供的API接口&#xff0c;可以轻松实现多种功能&#xff0c;如域名反查、域名备案查询、IPV6归属地查询等。这些功能可以帮助网站管理员更好地管理和优化自己的网站。以下是简单的代码示例&#xff0c;展示了如何使用站…

康姿百德公司官网柔压磁性枕豪华款高科技邂逅温柔夜活力满满!

康姿百德豪华柔压磁性枕慢回弹拥抱每寸肌肤&#xff0c;科技面料让呼吸自由夜夜好眠不是梦&#xff01; 现代家居设计不仅注重美观&#xff0c;更强调功能性和舒适性。康姿百德柔压磁性枕&#xff08;豪华款&#xff09;通过将高科技材料与创新设计结合&#xff0c;为我们的家…

Java反序列化漏洞-TemplatesImpl利用链分析

文章目录 一、前言二、正文1. 寻找利用链2. 构造POC2.1 生成字节码2.2 加载字节码1&#xff09;getTransletInstance2&#xff09;defineTransletClasses 2.3 创建实例 3. 完整POC 三、参考文章 一、前言 java.lang.ClassLoader#defineClass defineClass可以加载字节码&…

最大N个数与最小N个数的和

题目描述 给定一个数组&#xff0c;编写一个函数来计算它的最大N个数与最小N个数的和。你需要对数组进行去重 说明: 数组中数字范围[0&#xff0c;1000]最大N个数与最小N个数不能有重叠&#xff0c;如有重&#xff0c;输入非法返回-1输入非法返回-1 输入描述 第一行输入M&a…

uboot:配置编译

了解BSP 在嵌入式系统中&#xff0c;BSP&#xff08;Board Support Package&#xff09;被称为板级支持包或板级支持软件。它是一组针对特定硬件平台的软件支持包&#xff0c;为开发人员提供了一个统一的接口层&#xff0c;简化了硬件和软件之间的交互。BSP的主要功能和特点如…

Python数据分析-绘制图表

示例1&#xff1a; from pyecharts.charts import Bar # 柱状图 from pyecharts import options as optsfrom pyecharts.render import make_snapshotbar Bar() bar.add_xaxis([一月, 二月, 三月, 四月, 五月]) bar.add_yaxis("销售额", [10, 20, 15, 25, 30])# 配…

spring 事物使用场景说明

事务使用场景。 在某些业务场景下&#xff0c;如果一个请求中&#xff0c;需要同时写入多张表的数据。为了保证操作的原子性&#xff08;要么同时成功&#xff0c;要么同时失败&#xff09;&#xff0c;避免数据不一致的情况&#xff0c;我们一般都会用到spring事务。 确实&am…