LeetCode 39. 组合总和 LeetCode 40.组合总和II LeetCode 131.分割回文串

news2025/7/10 14:18:44

LeetCode 39. 组合总和

需要注意的是题目已经明确了数组内的元素不重复(重复的话需要执行去重操作),且元素都为正整数(如果存在0,则会出现死循环)。

思路1:暴力解法 + 对最后结果进行去重

  • 每一层的遍历都是遍历整个数组,深度遍历也是遍历该数组

Code

class Solution(object):
    def combinationSum(self, candidates, target):
        """
        :type candidates: List[int]
        :type target: int
        :rtype: List[List[int]]
        """

        ### candidates:即进行横向遍历,又进行深度遍历
        self.result = []
        self.path = []
        self.sum = 0
        if target < 2:
            return self.result

        sorted_candidates = sorted(candidates)
        self.backtracking(sorted_candidates, target)
        #return self.result

### 根据输出结果进行去重操作实现的
        denums = set()                              
        final_result = []
        for sub_array in self.result:
            sorted_sub_array = sorted(sub_array)
            denums_tuple = tuple(sorted_sub_array)
            if denums_tuple not in denums:
                denums.add(denums_tuple)
                final_result.append(sub_array)
        
        return final_result              #### 如何对输出组合进行去重? 又或者如何在回溯的过程中进行去重


    def backtracking(self, candidates, target):

        if self.sum == target:                      ### 终止条件 
            self.result.append(list(self.path))
            return 
        if self.sum > target:
            return 

        for i in range(len(candidates)):            ### 横向遍历
            self.path.append(candidates[i])
            self.sum += candidates[i]
            self.backtracking(candidates, target)   ### 深度遍历
            self.sum -= candidates[i]
            self.path.pop()                         ### 回溯           

思路2:对组合出现一样的问题进行优化

思路1为什么会出现重复的组合,因为比如说从第一层到第二层,你第一个节点是选取了2,然后后续2是不是会选取3,那这样就构成了组合[2,3],你如果你第二个节点从3开始还要去从2开始获取,那你就得到了组合[3,2],这样的话[2,3]和[3,2]就重复了,因此某个处理节点时,下一层的处理节点需要从当前元素开始到后续所有节点,而不再去判断之前的节点了,这样的话就重复判断了。

Code

class Solution(object):
    def combinationSum(self, candidates, target):
        """
        :type candidates: List[int]
        :type target: int
        :rtype: List[List[int]]
        """

        ### candidates:即进行横向遍历,又进行深度遍历
        self.result = []
        self.path = []
        self.sum = 0
        if target < 2:
            return self.result

        sorted_candidates = sorted(candidates)
        self.backtracking(0, sorted_candidates, target)
        return self.result

    def backtracking(self, start_index, candidates, target):

        if self.sum == target:                      ### 终止条件 
            self.result.append(list(self.path))
            return 
        if self.sum > target:
            return 

        for _ in range(start_index, len(candidates)):            ### 横向遍历
            self.path.append(candidates[start_index])
            self.sum += candidates[start_index]
            self.backtracking(start_index, candidates, target)   ### 深度遍历
            self.sum -= candidates[start_index]
            self.path.pop()                         ### 回溯           
            start_index += 1

继续优化,对思路2进行剪枝操作。思路是先对数组进行排序,将self.sum的值进行判断,如果其大于target了,后续的元素就不用进行深度遍历了。比如说一个数组为[2,3,5,7,8],目标target是6,当已遍历组合为[2,3]时,此时[2,3] 再判断把3放进来后是否等于target,但当前2+3+3=8 > target,因此是不成立的,原本的是执行完对3这个元素遍历完后,通过判断self.sum和target的值来退出,并且后续还会再去判断[2,3]跟7,8结合时的情况,但如果数组是有序,你现在就已经知道当前[2,3]跟3结合后已经大于target,那当前3之后的元素就可以不用进行遍历,因为继续遍历的话也是大于target。

Code

class Solution(object):
    def combinationSum(self, candidates, target):
        """
        :type candidates: List[int]
        :type target: int
        :rtype: List[List[int]]
        """

        ### candidates:即进行横向遍历,又进行深度遍历
        self.result = []
        self.path = []
        self.sum = 0
        if target < 2:
            return self.result

        sorted_candidates = sorted(candidates)
        self.backtracking(0, sorted_candidates, target)
        return self.result

    def backtracking(self, start_index, candidates, target):

        if self.sum == target:                      ### 终止条件 
            self.result.append(list(self.path))
            return 
        if self.sum > target:
            return 

        for _ in range(start_index, len(candidates)):            ### 横向遍历
            if self.sum + candidates[start_index] > target:     ### 剪枝
                break
            self.path.append(candidates[start_index])
            self.sum += candidates[start_index]
            self.backtracking(start_index, candidates, target)   ### 深度遍历
            self.sum -= candidates[start_index]
            self.path.pop()                         ### 回溯           
            start_index += 1

LeetCode 40.组合总和II

思路:

  • 每个元素只能使用一次,那递归的start_index 就从 start_index + 1 开始即可满足要求。
  • 难点在于如何进行树层的去重,即横向存在相同的元素的话,后续相同元素不需要进行深度遍历,因为遍历结果都已经全部被前面第一个元素给遍历过了。
  • 那树层如何进行去重呢?可以将数组的去重思想拿过来,但这样的话会存在问题,每个元素只能使用一次不代表不能使用相同的元素,这意味着我在竖向深度遍历的过程中是可以前一个元素和当前元素相同的。因此,如何进行树层的遍历,需要基于一个used数组来进行优化,这个数组与输入数组长度一致,其为布尔类型,当某个位置的元素正在被使用时,其在used中相同索引下标的值为True。 
  • used[start_index-1] == False是为了明确当前不是树枝方向上的去重,当前使用的元素跟上一个元素是相等的可以是竖向遍历的情况,而如果上一个元素目前没被使用,而我当前元素的值却跟上一个元素的值一样,那就证明了是在同一层上。

Code:

class Solution(object):
    def combinationSum2(self, candidates, target):
        """
        :type candidates: List[int]
        :type target: int
        :rtype: List[List[int]]
        """
        ### 对数组进行排序,继续按照“组合总和”的思路进行解决.
        ### 并且每个元素只能使用一次
        ###但需要执行去重操作,如果当前处理元素跟上一个元素相同的话,则需要跳过当前元素操作,去执行下一个元素。

        self.result = []
        self.path   = []
        self.sum = 0
        used = [False] * len(candidates)           ### used的作用是为了进行树层的去重。在同一层上used为True是数量一定是相等的,不同层之间used为True的数量一定不等,下一层总是比上一层多一个
        sorted_candidates = sorted(candidates)
        self.backtracking(sorted_candidates, target, 0, used)
        return self.result

    def backtracking(self, candidates, target, start_index, used):
        
        if self.sum == target:                           ### 终止条件
            self.result.append(list(self.path)) 
            return 
        if self.sum > target:
            return 
        
        for _ in range(start_index, len(candidates)):   ## 横向遍历
            if self.sum + candidates[start_index] > target:          ## 剪枝
                break
            if start_index > 0 and candidates[start_index] == candidates[start_index-1] and used[start_index-1] == False:    
                ### 去重.  如何设计去重只是针对当前横向的遍历而不包含竖向的遍历。(本题的关键也是本题的难点)
                ### 首先,candidates[start_index] == candidates[start_index-1]只是说明了我当前使用的元素跟上一个元素是相等的,符合每个元素只使用一次。
                ### used[start_index-1] == False是为了明确当前不是树枝方向上的去重,当前使用的元素跟上一个元素是相等的可以是竖向遍历的情况
                start_index += 1                ## 执行下个元素的操作
                continue                    
            used[start_index] = True        ### 修改used数组,表示我当前used start_index位置的元素是正在使用的
            self.path.append(candidates[start_index])
            self.sum += candidates[start_index]
            self.backtracking(candidates, target, start_index+1, used)        ### 每个数字在每个组合中只能使用 一次 
            self.path.pop()
            self.sum -= candidates[start_index]
            used[start_index] = False       ### 使用完元素后,进行回溯
            start_index += 1

LeetCode 131.分割回文串

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

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

相关文章

如何在 Windows 11 或 10 上安装 Fliqlo 时钟屏保

了解如何在 Windows 11 或 10 上安装 Fliqlo,为您的 PC 或笔记本电脑屏幕添加一个翻转时钟屏保以显示时间。 Fliqlo 是一款适用于 Windows 和 macOS 平台的免费时钟屏保。它也适用于移动设备,但仅限于 iPhone 和 iPad。Fliqlo 的主要功能是在用户不活动时在 PC 或笔记本电脑…

国芯思辰| 轮速传感器AH741对标TLE7471应用于汽车车轮速度感应

在汽车应用中&#xff0c;轮速传感器可用于车轮速度感应&#xff0c;为 ABS、ESC 等安全系统提供精确的轮速信息&#xff0c;帮助这些系统更好地发挥作用&#xff0c;在紧急制动或车辆出现不稳定状态时&#xff0c;及时调整车轮的制动力或动力分配。 国芯思辰两线制差分式轮速…

小程序弹出层/抽屉封装 (抖音小程序)

最近忙于开发抖音小程序&#xff0c;最想吐槽的就是&#xff0c;既没有适配的UI框架&#xff0c;百度上还找不到关于抖音小程序的案列&#xff0c;我真的很裂开啊&#xff0c;于是我通过大模型封装了一套代码 效果如下 介绍 可以看到 这个弹出层是支持关闭和标题显示的&#xf…

电子电路原理第十六章(负反馈)

1927年8月,年轻的工程师哈罗德布莱克(Harold Black)从纽约斯塔顿岛坐渡轮去上班。为了打发时间,他粗略写下了关于一个新想法的几个方程式。后来又经过反复修改, 布莱克提交了这个创意的专利申请。起初这个全新的创意被认为像“永动机”一样愚蠢可笑,专利申请也遭到拒绝。但…

命令拼接符

Linux多命令顺序执行符号需要记住5个 【&#xff5c;】【||】【 ;】 【&】 【&&】 &#xff0c;在命令执行里面&#xff0c;如果服务器疏忽大意没做限制&#xff0c;黑客通过高命令拼接符&#xff0c;可以输入很多非法的操作。 ailx10 网络安全优秀回答者 互联网…

【通用智能体】Lynx :一款基于终端的纯文本网页浏览器

Lynx &#xff1a;一款基于终端的纯文本网页浏览器 一、Lynx简介二、应用场景及案例场景 1&#xff1a;服务器端网页内容快速查看场景 2&#xff1a;网页内容快速提取场景 3&#xff1a;表单提交与自动化交互场景 4&#xff1a;网络诊断与调试场景 5&#xff1a;辅助工具适配 三…

51单片机的lcd12864驱动程序

#include <reg51.h> #include <intrins.h>#define uchar

GStreamer (三)常⽤插件

常⽤插件 1、Source1.1、filesrc1.2. videotestsrc1.3. v4l2src1.4. rtspsrc和rtspclientsink 2、 Sink2.1. filesink2.2. fakesink2.3. xvimagesink2.4. kmssink2.5. waylandsink2.6. rkximagesink2.7. fpsdisplaysink 3 、视频推流/拉流3.1. 本地推流/拉流3.1.1 USB摄像头3.1…

软件架构风格系列(2):面向对象架构

文章目录 引言一、什么是面向对象架构风格1. 定义与核心概念2. 优点与局限性二、业务建模&#xff1a;用对象映射现实世界&#xff08;一&#xff09;核心实体抽象1. 员工体系2. 菜品体系 &#xff08;二&#xff09;封装&#xff1a;隐藏实现细节 三、继承实战&#xff1a;构建…

go-zero(十八)结合Elasticsearch实现高效数据检索

go-zero结合Elasticsearch实现高效数据检索 1. Elasticsearch简单介绍 Elasticsearch&#xff08;简称 ES&#xff09; 是一个基于 Lucene 库 构建的 分布式、开源、实时搜索与分析引擎&#xff0c;采用 Apache 2.0 协议。它支持水平扩展&#xff0c;能高效处理大规模数据的存…

AM32电调学习解读九:ESC上电启动关闭全流程波形分析

这是第九篇&#xff0c;前面的文章把各个模块的实现都介绍了一轮&#xff0c;本章是从运行的角度结合波形图&#xff0c;把整个流程走一遍。 先看下一运行的配置&#xff0c;我把一些配置关闭了&#xff0c;这样跑起来会好分析一些&#xff0c;不同配置跑起来效果会有差异。使用…

【notes】VScode 使用总结

文章目录 扩展 c/cwindows7 系统下 c/c 自动升级导致的插件无法正常使用 设置 文件格式设置打开文件的默认格式 扩展 c/c windows7 系统下 c/c 自动升级导致的插件无法正常使用 问题 1. c/c扩展的1.25.x版本不再支持windows7 系统&#xff0c;当设置VScode自动升级拓展插件时…

【论文阅读】KIMI K1.5: SCALING REINFORCEMENT LEARNING WITH LLMS

KIMI K1.5: SCALING REINFORCEMENT LEARNING WITH LLMS Scaling的解释&#xff1a; 通过系统性的方法扩展强化学习算法的能力&#xff0c;使其能够处理更复杂的问题、更大的状态/动作空间、更长的训练周期或更高效的资源利用 原文摘要&#xff1a; 研究背景与问题定位 传统预训…

Qwen3 - 0.6B与Bert文本分类实验:深度见解与性能剖析

Changelog [25/04/28] 新增Qwen3-0.6B在Ag_news数据集Zero-Shot的效果。新增Qwen3-0.6B线性层分类方法的效果。调整Bert训练参数&#xff08;epoch、eval_steps&#xff09;&#xff0c;以实现更细致的观察&#xff0c;避免严重过拟合的情况。 TODO&#xff1a; 利用Qwen3-0.6…

UWB定位方案在水力发电站人员安全的应用推荐

一、行业应用背景‌ 水力发电站具有‌环境复杂‌&#xff08;金属设备密集、高温高压区域多&#xff09;、‌安全风险高‌&#xff08;人员误入高危区域易引发事故&#xff09;等特点&#xff0c;传统定位技术难以满足精度与可靠性要求。品铂科技基于UWB的高精度定位系统已在多…

无刷直流水泵构成及工作原理详解--【其利天下技术】

无刷直流水泵是相对于有刷直流泵而言的。 一&#xff1a;无刷直流水泵简介 无刷直流水泵即BLDC PUMP&#xff0c;其中“BL”意为“无刷”&#xff0c;DC即直流电机。 无刷直流水泵(BLDC PUMP)以电子换向器取代了机械换向器&#xff0c;所以无刷直流水泵既具有直流电机良好的调…

大数据:新能源汽车宇宙的未来曲率引擎

** 发布日期&#xff1a;2025-05-14** 关键词&#xff1a;大数据、新能源、机器学习、碳中和、CSDN爆款 1. 大数据科普&#xff1a;定义、特征与技术核心 1.1 什么是大数据&#xff1f; 大数据&#xff08;Big Data&#xff09;指规模巨大、类型多样、生成速度快且价值密度低…

【Java ee】关于抓包软件Fiddler Classic的安装与使用

Web Debugging Proxy Tool | Fiddler Classic 安装网站↑ 下载好安装包之后&#xff0c;双击一路next就可以了 一、抓包软件 电脑上安装了抓包软件之后&#xff0c;抓包软件就可以监听你的网卡上通过的数据。 本来是你的客户端通过网卡&#xff0c;把数据发给目标服务器&a…

C++--内存管理

内存管理 1. C/C内存分布 在C语言阶段&#xff0c;常说局部变量存储在栈区&#xff0c;动态内存中的数据存储在堆区&#xff0c;静态变量存储在静态区&#xff08;数据段&#xff09;&#xff0c;常量存储在常量区&#xff08;代码段&#xff09;&#xff0c;其实这里所说的栈…

TC3xx学习笔记-UCB BMHD使用详解(二)

文章目录 前言Confirmation的定义Dual UCB: Confirmation StatesDual UCB: Errored State or ECC Error in the UCB Confirmation CodesECC Error in the UCB ContentDual Password UCB ORIG and COPY Re-programming UCB_BMHDx_ORIG and UCB_BMHDx_COPY (x 0-3)BMHD Protecti…