Python算法题集_组合总和

news2025/2/24 2:22:05

 Python算法题集_组合总和

  • 题39:组合总和
  • 1. 示例说明
  • 2. 题目解析
    • - 题意分解
    • - 优化思路
    • - 测量工具
  • 3. 代码展开
    • 1) 标准求解【值传递+回溯】
    • 2) 改进版一【引用传递+堆栈回溯】
    • 3) 改进版二【过程值列表缓存+遍历后检索】
  • 4. 最优算法
  • 5. 相关资源

本文为Python算法题集之一的代码示例

题39:组合总和

1. 示例说明

  • 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。

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

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

    示例 1:

    输入:candidates = [2,3,6,7], target = 7
    输出:[[2,2,3],[7]]
    解释:
    2 和 3 可以形成一组候选,2 + 2 + 3 = 7 。注意 2 可以使用多次。
    7 也是一个候选, 7 = 7 。
    仅有这两种组合。
    

    示例 2:

    输入: candidates = [2,3,5], target = 8
    输出: [[2,2,2,2],[2,3,3],[3,5]]
    

    示例 3:

    输入: candidates = [2], target = 1
    输出: []
    

    提示:

    • 1 <= candidates.length <= 30
    • 2 <= candidates[i] <= 40
    • candidates 的所有元素 互不相同
    • 1 <= target <= 40

2. 题目解析

- 题意分解

  1. 本题是计算多个集合之间的求和问题,每个集合由若干个同样的整数组成
  2. 同样整数和不能超过target,所以多个集合都是有限集合,因此每个集合能合成出来的数值也是有限的,可以用回溯法求解
  3. 回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法。

- 优化思路

  1. 通常优化:减少循环层次

  2. 通常优化:增加分支,减少计算集

  3. 通常优化:采用内置算法来提升计算速度

  4. 分析题目特点,分析最优解

    1. 可以在回溯算法中使用值传递

    2. 可以在回溯算法中使用引用传递,但是应用传递必须解决回退操作,可以使用堆栈结构

    3. 可以考虑存储过程值列表,最后将等于target的集合返回


- 测量工具

  • 本地化测试说明:LeetCode网站测试运行时数据波动很大【可把页面视为功能测试】,因此需要本地化测试解决数据波动问题
  • CheckFuncPerf(本地化函数用时和内存占用测试模块)已上传到CSDN,地址:Python算法题集_检测函数用时和内存占用的模块
  • 本题本地化超时测试用例自己生成,详见章节【最优算法】,代码文件包含在【相关资源】中

3. 代码展开

1) 标准求解【值传递+回溯】

使用列表作为值传递参数,逐层递归,完成回溯

页面功能测试,马马虎虎,超过40%在这里插入图片描述

import CheckFuncPerf as cfp

class Solution:
 def combinationSum_base(self, candidates, target):
     def bracktracing(candidates, begin, ilen, path, ret, target):
         if target < 0:
             return
         if target == 0:
             ret.append(path)
             return
         for iIdx in range(begin, ilen):
             bracktracing(candidates, iIdx, ilen, path + [candidates[iIdx]], ret, 
                          target - candidates[iIdx])
     ilen = len(candidates)
     path, result = [], []
     if ilen == 0:
         return result
     bracktracing(candidates, 0, ilen, path, result, target)
     return result

aSolution = Solution()
result = cfp.getTimeMemoryStr(aSolution.combinationSum_base, nums, target)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))

# 运行结果
函数 combinationSum_base 的运行时间为 1076.25 ms;内存使用量为 12060.00 KB 执行结果 = 62271

2) 改进版一【引用传递+堆栈回溯】

使用列表作为引用传递参数,逐层递归,完成回溯

页面功能测试,马马虎虎,超越71%在这里插入图片描述

import CheckFuncPerf as cfp

class Solution:
 def combinationSum_ext1(self, candidates, target):
     candidates.sort()
     path, result = [], []
     idx, isum = 0, 0
     def bracktracing(idx, isum, path):
         if sum(path) == target:
             result.append(path[:])
             return
         for jIdx in range(idx, len(candidates)):
             if isum + candidates[jIdx] > target:
                 return
             path.append(candidates[jIdx])
             isum += candidates[jIdx]
             bracktracing(jIdx, isum, path)
             path.pop()
             isum -= candidates[jIdx]
     bracktracing(idx, isum, path)
     return result

aSolution = Solution()
result = cfp.getTimeMemoryStr(aSolution.combinationSum_base, nums, target)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))

# 运行结果
函数 combinationSum_base 的运行时间为 1076.25 ms;内存使用量为 12060.00 KB 执行结果 = 62271

3) 改进版二【过程值列表缓存+遍历后检索】

使用多维列表结构保存各数值对应的组合列表,遍历完成后下标检索对应组合列表

页面功能测试,马马虎虎,超过23%在这里插入图片描述

import CheckFuncPerf as cfp

class Solution:
 def combinationSum_ext2(self, candidates, target):
     import copy
     candidates.sort()
     dp = [[] for x in range(target + 1)]
     for candidate in candidates:
         for iIdx in range(candidate, target + 1):
             if candidate == iIdx:
                 dp[iIdx].append([candidate])
             else:
                 for combination in dp[iIdx - candidate]:
                     tmpgroup = copy.deepcopy(combination)
                     tmpgroup.append(candidate)
                     dp[iIdx].append(tmpgroup)
     return dp[target]

aSolution = Solution()
result = cfp.getTimeMemoryStr(aSolution.combinationSum_base, nums, target)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))

# 运行结果
函数 combinationSum_base 的运行时间为 1076.25 ms;内存使用量为 12060.00 KB 执行结果 = 62271

4. 最优算法

根据本地日志分析,最优算法为第1种方式【值传递+回溯】combinationSum_base

本题测试数据,似乎能推出以下结论:

  1. 组合的回溯求解中,值传递性能优于引用传递的堆栈结构
  2. 内存对象过多后,性能下降明显,如combinationSum_ext2
nums = [x for x in range(10, 20)]
target = 200
aSolution = Solution()
result = cfp.getTimeMemoryStr(aSolution.combinationSum_base, nums, target)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))
result = cfp.getTimeMemoryStr(aSolution.combinationSum_ext1, nums, target)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))
result = cfp.getTimeMemoryStr(aSolution.combinationSum_ext2, nums, target)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))

# 算法本地速度实测比较
函数 combinationSum_base 的运行时间为 1076.25 ms;内存使用量为 12060.00 KB 执行结果 = 62271
函数 combinationSum_ext1 的运行时间为 1243.29 ms;内存使用量为 11848.00 KB 执行结果 = 62271
函数 combinationSum_ext2 的运行时间为 14627.27 ms;内存使用量为 16080.00 KB 执行结果 = 62271

5. 相关资源

本文代码已上传到CSDN,地址:Python算法题源代码_LeetCode(力扣)_组合总和

一日练,一日功,一日不练十日空

may the odds be ever in your favor ~

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

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

相关文章

【办公类-22-07】周计划系列(3-2)“信息窗+主题知识(优化)” (2024年调整版本)

作品展示&#xff1a; 背景需求 前文对“2023年2月”的一套信息窗主题知识的文件系列&#xff0c;进行第一次的提取。获得基础模板。 【办公类-22-07】周计划系列&#xff08;3-1&#xff09;“信息窗主题知识&#xff08;提取&#xff09;” &#xff08;2024年调整版本&…

面试官问我Redis怎么测,我哪知道!

有些测试朋友来问我&#xff0c;redis要怎么测试&#xff1f;首先我们需要知道&#xff0c;redis是什么&#xff1f;它能做什么&#xff1f; redis是一个key-value类型的高速存储数据库。 redis常被用做&#xff1a;缓存、队列、发布订阅等。 所以&#xff0c;“redis要怎么测试…

理解计算着色器中glsl语言的内置变量

概要 本文通过示例的方式&#xff0c;着重解释以下几个内置变量&#xff1a; gl_WorkGroupSizegl_NumWorkGroupsgl_LocalInvocationIDgl_WorkGroupIDgl_GlobalInvocationID 基本概念 局部工作组与工作项 一个3x2x1的局部工作组示例如下&#xff0c;每个小篮格子表示一个工作项…

简单了解B树和B+树

目录 B树 B树 B树和B树的结构示意图 总结 B树和B树是两种非常重要的树状数据结构&#xff0c;它们广泛应用于数据库和文件系统的索引结构中。这两种数据结构能够帮助我们高效地管理、查询以及更新大量的数据。下面&#xff0c;我将简单介绍它们,以及他们之间的区别。 B树 B…

【leetcode】链表的中间节点

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家刷题&#xff0c;如果你觉得我写的还不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 目录 点击查看题目 思路: slow和fast都初始化为head&#xff0c;之后slow每走1步&#xff0c;fast走2步…

枚举(蓝桥练习)(反倍数、特别数的和、找到最多的数、小蓝的漆房、小蓝和小桥的挑战)

目录 一、枚举算法介绍 二、解空间的类型 三、循环枚举解空间 四、例题 &#xff08;一、反倍数&#xff09; &#xff08;二、特别数的和&#xff09; &#xff08;三、找到最多的数&#xff09; &#xff08;四、小蓝的漆房&#xff09; &#xff08;五、小蓝和小桥的…

【力扣hot100】刷题笔记Day17

前言 今天竟然不用开组会&#xff01;天大的好消息&#xff0c;安心刷题了 46. 全排列 - 力扣&#xff08;LeetCode&#xff09; 回溯&#xff08;排列&#xff09; class Solution:def permute(self, nums: List[int]) -> List[List[int]]:# 回溯def backtrack():if len(…

一、前端开发

#视频链接&#xff1a;https://www.bilibili.com/video/BV1rT4y1v7uQ?p1&vd_source1717654b9cbbc6a773c2092070686a95 前端开发 前端开发1、快速开发网站2、浏览器能识别的标签2.1 编码&#xff08;head&#xff09;2.2 title(head)2.3 标题2.4 div和span练习题2.5 超链接…

如何做代币分析:以 USDT 币为例

作者&#xff1a;lesleyfootprint.network 编译&#xff1a;cicifootprint.network 数据源&#xff1a;USDT Token Dashboard &#xff08;仅包括以太坊数据&#xff09; 在加密货币和数字资产领域&#xff0c;代币分析起着至关重要的作用。代币分析指的是深入研究与代币相关…

prometheus监控带安全认证的elasticsearch

1.下载elasticsearch_exporter wget 下载二进制包并解压、运行&#xff1a; wget https://github.com/prometheus-community/elasticsearch_exporter/releases/download/v1.3.0/elasticsearch_exporter-1.3.0.linux-amd64.tar.gz tar -xvf elasticsearch_exporter-1.3.0.lin…

imazing是啥 ?iMazing 3.0.0.3中文版会有哪些新功能?

imazing是啥 imazing是管理iOS设备的软件 iMazing 是一款用于管理iOS设备的软件。它支持在Windows和Mac电脑上对基于iOS系统的设备进行数据传输、备份和管理。用户可以通过这款软件传输和备份包括照片、音乐、铃声、视频、电子书及通讯录等多种信息。不仅限于iPhone、iPad或iP…

1、docker 基础命令

1、docker 运行镜像 docker run image tag 2、创建dockerfile&#xff08;构建容器的相关命令&#xff09; vim DockerFile 3、docker 构建容器镜像 docker build -t <image_name> . 4、docker 分层 5、查看镜像 docker images 6、docker 执行 docker run --name &…

言语理解与表达-郭熙-02

1、上节回顾 1.1 转折关系 1.2 因果关系 1.3 主题词 2、本课目录 3、必要条件关系 3.1 题目 4、对策类 4.1 题目 5、反面论证 提对策 题目 6、必要关系总结 7、程度词 题目 易错&#xff1a; 8、并列关系 题目 易错&#xff1a;

Java面试题之并发

并发 1.并发编程的优缺点&#xff1f;2.并发编程三要素&#xff1f;3.什么叫指令重排&#xff1f;4.如何避免指令重排&#xff1f;5.并发&#xff1f;并行&#xff1f;串行&#xff1f;6.线程和进程的概念和区别&#xff1f;7.什么是上下文切换&#xff1f;8.守护线程和用户线程…

lv20 QT对话框3

1 内置对话框 标准对话框样式 内置对话框基类 QColorDialog, QErrorMessage QFileDialog QFontDialog QInputDialog QMessageBox QProgressDialogQDialog Class帮助文档 示例&#xff1a;各按钮激发对话框实现基类提供的各效果 第一步&#xff1a;实现组件布局&…

dolphinscheduler集群部署教程

文章目录 前言一、架构规划二、配置集群免密登录1. 配置root用户集群免密登录1.1 hadoop101节点操作1.2 hadoop102节点操作1.3 hadoop103节点操作 2. 创建用户2.1 hadoop101节点操作2.2 hadoop102节点操作2.3 hadoop103节点操作 三、安装准备1. 安装条件2. 安装jdk3. 安装MySQL…

FreeRTOS 信号量

目录 一、信号量的概念 二、二值信号量 1、二值信号量的定义 2、二值信号量的作用 3、二值信号量的操作 4、二值信号量操作实验 5、二值信号量会导致优先级翻转问题 三、互斥信号量 1、互斥信号量的引入 2、注意&#xff1a;互斥信号量不能用于中断服务函数中&#xf…

kali linux通过aircrack-ng命令破解wifi密码

相关阅读&#xff1a;如何破解攻击WiFi 百度安全验证https://baijiahao.baidu.com/s?id1764248756021219497&wfrspider&forpc上面2篇文章写得都很不错 一、前期准备工作 1、将无线网卡挂载到Kali上 ​ 将无线网卡插到电脑上&#xff0c;如果弹出检测到新的USB设备&…

戏说c语言: 阶段性总结二

前言 师弟&#xff1a;“师兄&#xff0c;我终于和我喜欢的女生在一起了。感谢师兄呀。” 我&#xff1a;“恭喜啊&#xff0c;师弟&#xff01;” 师弟&#xff1a;“这要全靠这段学习c的缘分了啊&#xff0c;两个人没事交流c语言&#xff0c;一起去上课&#xff0c;共同成长…

vue3使用echarts绘制地图

vue3使用echarts绘制地图 安装echarts npm install echarts下载地图的json数据【我这里是把json数据单独粘出来然后新建了一个文件china.json】 下载中国及各个省份的地图数据引入 import chinaJson from ./china.json绘制地图 <template><div ref"myChart&q…