代码随想录|Day23|回溯03|39.组合总和、40.组合总和II、131.分割回文串

news2024/11/15 21:29:20

39.组合总和

本题和 216.组合总和III 类似,但有几个区别:

  1. 没有元素个数限制:树的深度并不固定,因此递归终止条件有所变化
  2. 每个元素可以使用多次:下层递归的起始位置和上层相同(startIndex不需要改动)

class Solution:
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        
        def backtrack(startIndex, path, currentSum):
            # 和大于等于目标的时候终止
            # 如果等于目标,还需要先收集
            if currentSum >= target:
                if currentSum == target:
                    result.append(path[:])
                return
            
            for i in range(startIndex, len(candidates)):
                path.append(candidates[i])
                currentSum += candidates[i]
                # 下层递归的起始位置和本层相同
                backtrack(i, path, currentSum)
                path.pop()
                currentSum -= candidates[i]
        
        result = []
        backtrack(startIndex = 0, path = [], currentSum = 0)
        return result

 剪枝:如果我们事先对 candidates 排序,那么下一层递归的 currentSum 一定会更大,在此之前判断 currentSumtarget 的判断可以实现剪枝。

为什么要排序?举个例子,假设总和为 4,那么 [2, 2] 符合条件,下一次搜索可能获得 [2, 1, 1] 也是符合条件的,如果排序则可以确保接下来搜索的元素更大,换句话说 [2, 1, 1] 一定在 [2, 2] 之前被找到。

class Solution:
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        
        def backtrack(startIndex, path, currentSum):
            # 和大于等于目标的时候终止
            # 如果等于目标,还需要先收集
            if currentSum >= target:
                if currentSum == target:
                    result.append(path[:])
                return
            
            for i in range(startIndex, len(candidates)):
                # 剪枝:如果和已经超过,则不需要继续搜索
                if currentSum + candidates[i] > target: continue

                path.append(candidates[i])
                currentSum += candidates[i]
                # 下层递归的起始位置和本层相同
                backtrack(i, path, currentSum)
                path.pop()
                currentSum -= candidates[i]
        
        result = []
        candidates.sort()
        backtrack(startIndex = 0, path = [], currentSum = 0)
        return result

40.组合总和II

本题的关键是 candidates 中的元素可能重复,如果使用传统的方法递归,则结果很有可能包含重复组合。举个例子,假设 candidates = [1, 2, 2, 5]target = 3。当我们选择了 1,其递归出现 3个 分支:[1, 2]、[1, 2]、[1, 5],此时出现了重复组合。

class Solution:
    def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:

        def backtrack(startIndex, path, currentSum):
            if currentSum >= target:
                if currentSum == target:
                    result.append(path[:])
                return
            
            for i in range(startIndex, len(candidates)):
                # 如果当前数字与前一个数字相同,并且不是遍历的第一个数字,则跳过以避免重复组合
                if i > startIndex and candidates[i] == candidates [i-1]:
                    continue
                # 剪枝
                if currentSum + candidates[i] > target:
                    return                

                path.append(candidates[i])
                currentSum += candidates[i]

                backtrack(i + 1, path, currentSum)

                path.pop()
                currentSum -= candidates[i]
        
        result = []
        # 排序
        candidates.sort()
        backtrack(startIndex = 0, path = [], currentSum = 0)
        return result

131.分割回文串

本题可以理解为一个组合问题,我们组合不同的元素,判断是否为回文子串。 

class Solution:
    def partition(self, s: str) -> List[List[str]]:
        # 双指针判断是否为回文串
        def isPalindrome(subs):
            left, right = 0, len(subs)-1
            while left < right:
                if subs[left] != subs[right]:
                    return False
                left += 1
                right -= 1
            return True
        
        def backtrack(startIndex, path):
            # startIndex是我们的切割线
            # 因此递归终止条件为切割到末尾
            if startIndex >= len(s):
                result.append(path[:])
                return
            
            for i in range(startIndex, len(s)):
                # [startIndex, i]为我们的切割子串
                if isPalindrome(s[startIndex: i+1]):
                    path.append(s[startIndex: i+1])
                    backtrack(i+1, path)
                    path.pop()
            
        result = []
        backtrack(startIndex = 0, path = [])
        return result

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

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

相关文章

#每天一道面试题# 什么是MySQL的回表查询

MySQL中的索引按照物理存储的方式分为聚集索引和非聚集索引&#xff1b; 聚集索引索引和数据存储在一起&#xff0c;B树的叶子节点就是表数据&#xff0c;如果通过聚集索引查询数据&#xff0c;直接就可以查询出我们想要的数据&#xff1b;非聚集索引B树的叶子节点存储的是主键…

Hive SQL必刷练习题:连续问题 间断连续(*****)

问题描述&#xff1a; 1&#xff09; 连续问题&#xff1a;找出连续三天&#xff08;或者连续几天的啥啥啥&#xff09;。 2&#xff09; 间断连续&#xff1a;统计各用户连续登录最长天数&#xff0c;间断一天也算连续&#xff0c;比如1、3、4、6也算登陆了6天 问题分析&am…

Java八股文(XXL-JOB)

Java八股文のXXL-JOB XXL-JOB XXL-JOB xxl-job 是什么&#xff1f;它的主要作用是什么&#xff1f; xxl-job 是一款分布式任务调度平台&#xff0c;用于解决分布式系统中的定时任务和异步任务调度问题。 它提供了任务的注册、调度、执行和监控等功能&#xff0c;能够帮助开发者…

激光打标机的维护与保养:确保设备长期稳定运行的关键

​ 激光打标机的维护与保养是确保设备长期稳定运行的关键&#xff0c;以下是一些关键的维护和保养步骤&#xff1a; 一、定期清洁 1. 清洁镜片&#xff1a;定期清洁激光打标机的镜片是维护保养的重要环节。使用纯净的酒精或专用的激光镜片清洗剂&#xff0c;轻轻擦拭镜片表面&…

WPS制作甘特图

“ 甘特图&#xff08;Gantt chart&#xff09;又称为横道图、条状图&#xff08;Bar chart&#xff09;&#xff0c;通过条状图来显示项目、进度和其他时间相关的系统进展的内在关系随着时间进展的情况。” 设置基础样式 设置行高 设置宽度 准备基础数据 计算持续时间 …

C语言数组—二维数组

二维数组的创建 //数组创建 int arr[3][4]; //三行四列&#xff0c;存放整型变量 double arr[2][4];二维数组的初始化 我们如果这样初始化&#xff0c;效果是什么样的呢 int arr[3][4] { 1,2,3,4,5,6,7,8,9,10,11,12 };那如果我们不写满十二个呢 int arr[3][4] { 1,2,3,4…

超实用!免费软件站大盘点,总有一款适合你

相信用Mac电脑的同学都知道一个网站MacWK&#xff0c;可以白嫖几乎所有常用软件&#xff0c;不用付费&#xff0c;但不好的消息是在2022年10月宣布关站&#xff0c;小编从此走上了开源免费的道路&#xff0c;尽管不太好用&#xff0c;奈何口袋木有钱&#xff0c;经过小编的不断…

一个页面请求从在浏览器中输入网址到页面最终呈现

前言-与正文无关 生活远不止眼前的苦劳与奔波&#xff0c;它还充满了无数值得我们去体验和珍惜的美好事物。在这个快节奏的世界中&#xff0c;我们往往容易陷入工作的漩涡&#xff0c;忘记了停下脚步&#xff0c;感受周围的世界。让我们一起提醒自己&#xff0c;要适时放慢脚步…

通过调整报文偏移解决CAN应用报文丢帧或周期过长问题

偏移原理 报文很多都是周期性发送的&#xff0c;但是如果每条报文都以一开始作为开始计时的时间点&#xff0c;也就是一开始就发送第一条报文&#xff0c;可能会导致CAN堵塞&#xff0c;导致丢帧或者某些报文某一时刻周期过长&#xff0c;就像下图这样&#xff0c;同一时刻CAN…

机器视觉引导的多材料3D打印

3D打印机使用机器视觉来解决困扰3D喷墨打印机的问题&#xff0c;增加了可以使用的材料范围&#xff0c;并实现了机器人手等复杂物体的快速生产。 增材制造&#xff08;也称为 3D 打印&#xff09;的进步已经产生了越来越强大的能力&#xff0c;可以生产使用传统制造工艺无法制…

CMake编译 c++源码入门教程

CMake 随着工程的越来越大&#xff0c;且需要跨平台的应用&#xff0c;Make工具也会相对麻烦。因此&#xff0c;2000年&#xff0c;由Kitware公司开发。CMake是一种跨平台的构建系统&#xff0c;它使用一种声明式的构建语言&#xff0c;允许用户通过简单的配置文件来定义项目的…

基于Andriod的连锁药店管理系统(源码|论文)

一、系统架构 前端&#xff1a;vue | uni-app 后端&#xff1a;spring | springmvc | mybatis 环境&#xff1a;jdk1.8 | mysql | maven | node 二、代码及数据库 三、功能介绍 01. 登录页 02. 管理后台-首页 03. 管理后台-个人中心-修改密码 04. 管理后台-个人中心-个…

嵌入式Linux 内核的内存管理方法

内存管理的主要工作就是对物理内存进行组织,然后对物理内存的分配和回收。但是Linux引入了虚拟地址的概念。 虚拟地址的作用 如果用户进程直接操作物理地址会有以下的坏处: 1、 用户进程可以直接操作内核对应的内存,破坏内核运行。 2、 用户进程也会破坏其他进程的运行 …

【Unity】CatlikeCoding SRP

Unity 自定义渲染管线 提示&#xff1a;基于CatlikeCoding SRP系列教程学习 学习链接&#xff1a;SRP 个人测试: Demo 相关记录以后有时间再更&#xff1a;

计算机考研|北航北理北邮怎么选?

北航985&#xff0c;北理985&#xff0c;北邮211 虽然北邮事211&#xff0c;但是北邮的计算机实力一点也不弱&#xff0c;学科评级&#xff0c;计算机是A 北航计算机评级也是A&#xff0c;北理的计算机评级是A- 所以&#xff0c;这三所学校在实力上来说&#xff0c;真的大差…

大模型知识积累——幻觉

什么是大模型幻觉 在大语言模型的文本生成场景下&#xff0c;幻觉是指一本正经的胡说八道。逻辑连贯的自然表述中&#xff0c;有理论或者事实错误&#xff0c;捏造事实等问题。 幻觉问题的危害 LLM幻觉可能产生传播错误知识的后果。对于医疗应用中结果安全和可信AI尤为重要&a…

研究揭示OpenAI GPT-3.5-Turbo模型参数量可能只有7B

加利福尼亚州&#xff0c;洛杉矶 - 一项由南加州大学计算机科学系的研究人员进行的新研究&#xff0c;通过创新的数学方法&#xff0c;对OpenAI公司的最新语言模型GPT-3.5-Turbo的内部结构进行了深入分析。研究团队通过一系列精心设计的“暴力提问”实验&#xff0c;成功地估计…

【全网最详细】ComfyUI下,Insightface安装指南-聚梦小课堂

&#x1f96e;背景 ComfyUI下使用IP-adapter下的faceID模型的时候&#xff0c;大家可能会遇到如下错误&#xff1a; Error occurred when executing InsightFaceLoader: No module named insightface File "F:\ComfyUI-aki\execution.py", line 151, in recursive_…

【四】常用数据层技术高可用方案1

常用数据层技术高可用方案 简介 做架构设计我们都要面临系统的三高问题&#xff0c;系统的三高是指高并发、高性能、高可用&#xff0c;这些是系统架构设计中的重要指标。 高并发是指系统能够同时处理大量请求的能力。每次设计架构我们都需要根据业务体量来估算系统需要具备的并…

可视化场景(5):生产监控,比摄像头好用多了。

hello&#xff0c;我是贝格前端工场&#xff0c;本期分享可视化大屏在生产监控场景的应用&#xff0c;如需要定制&#xff0c;可以与我们联络&#xff0c;开始了。 实时监控 可视化大屏可以实时展示生产线上的各种关键指标和数据&#xff0c;如生产速度、设备状态、产量、质量…