算法第十一天-组合总和Ⅳ

组合总和Ⅳ

题目要求

解题思路

来自[负雪明烛]
题目有个明显的提示:求组合的个数,而不是每个组合。如果是要求出每个组合,那么必须使用回溯法,保存所有路径。但是如果是组合个数,一般都应该想到[动态规划]的解法。
直接写出[动态规划]的解法,是有一定难度的。不妨先写出[记忆化递归],然后进行修改[动态规划]。

方法一:递归

要求构成target有多少种组合方法,这里的变量应该是target,所以,令函数dp(x)表示从nums中挑选数字可以构成x的方法数(递归最基本的就是理解这个定义!)。最终返回的应该是dp(target)
对于题目输入nums=[1,2,3],target =4的时候:要求有多少种方法能够组成4,即要求dp[4]。思考过程如下:
我们遍历nums,判断如果构成target的时候,选择了nums[i],那么剩余的target-nums[i]仍在nums中选择的话,会有多少种方法。
于是一步一步出现了递归。这就是将大问题拆成小问题,然后发现小问题恰好可以用同样的函数解决,这就是递归思想。递归是一种思想与现象,绝不是为了递归而递归。
那么递归终止条件是什么呢?也就是说最基础的case应该直接返回什么结果?

  • 如果给出的数字都是正整数,因此如果当要求的target<0的时候,无论如何都无法从数组中挑选元素构成,所以应该返回0;
  • 当要求的target==0 的时候,需要return 1。为什么?因为我们注意题目给出的输入target一定是大于0的,如果在递归的时候target==0,说明在for循环中的target-num得到了0,表示nums数组中乔安后有一个数字等于target。所以需要返回1。
    会超时。
    时间复杂度: O ( N t r a g e t ) O(N^{traget}) O(Ntraget),N是nums的长度,每次递归需要计算N次,递归深度最多target。
    空间复杂度: O ( t a r g e t ) O(target) O(target)

方法二:记忆化递归

上面递归方法会超时,是因为有重复计算,比如计算dp(4)的时候,计算了dp(2),而计算dp(3)的时候又再次计算了dp(2)。如果我们在递归的过程中,把已经计算了的结果放在数组、字典中保存,那么下次需要再计算相同的值的时候,直接从数组/字典中调用相同的计算结果,就能省下很多计算。
下面的代码演示了如何使用[记忆化递归]。定义了一个dp数组,保存已经计算量的每个dp(x)dp数组的每个位置初始化为-1,表示还没计算过。在递归函数刚开始的时候,不仅要判断target是否<0,还要判断当前计算的target是否计算过(即dp[target] !=-1)。只有在没计算过的情况下,才执行递归。并且在执行递归之后,需要把当前target的计算结果保存到dp数组中。

代码:
class Solution(object):def combinationSum4(self, nums, target):self.dp = [-1] * (target + 1)self.dp[0] = 1return self.dfs(nums, target)def dfs(self, nums, target):if target < 0: return 0if self.dp[target] != -1:return self.dp[target]res = 0for num in nums:res += self.dfs(nums, target - num)self.dp[target] = resreturn res
复杂度分析

时间复杂度: O ( N ∗ t a r g e t ) O(N * target) O(Ntarget)
空间复杂度: O ( t a r g e t ) O(target) O(target)

方法三:动态规划

理解了[记忆化递归]之后,离写出动态规划只有一步之遥。递归是自顶向下的计算方式(大问题-》小问题),而动态规划是自底向上的计算方式(小问题-》大问题)
动态规划也同样地定义dp数组,dp[i]表示从nums中抽取元素组成target的方案数。dp数组的长度是target+1。其中dp[0]表示从数组中抽取任何元素组成0的方案数,根据我们在递归时的分析,我们需要知道令dp[0] = 1。其他位置的dp[i]需要初始化为0,表示我们还没有计算过这个位置,默认的方案数为0。
想要计算得到target,需要把dp[1~target]的各个元素都计算出来。每个位置的计算都是为了后面的计算做准备。

代码:
class Solution(object):def combinationSum4(self, nums, target):dp = [0] * (target + 1)dp[0] = 1res = 0for i in range(target + 1):for num in nums:if i >= num:dp[i] += dp[i - num]return dp[target]
复杂度分析:

时间复杂度: O ( N ∗ t a r g e t ) O(N * target) O(Ntarget)
空间复杂度: O ( t a r g e t ) O(target) O(target)

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

企业常用的几种实用的加速FTP传输方式

FTP作为互联网上最早应用的文件传输协议之一&#xff0c;同时也是企业内外常用的文件和数据交换方式。然而&#xff0c;随着数据量的增加和对传输速度、稳定性、安全性等要求的提高&#xff0c;FTP传输面临一系列挑战&#xff0c;给企业的业务效率和数据安全带来了困扰。本文将…

第二百五十四回

文章目录 1. 概念介绍2. 思路与方法2.1 实现思路2.2 实现方法 3. 代码与效果3.1 示例代码3.2 运行效果 4. 内容总结 我们在上一章回中介绍了"如何给图片添加阴影"相关的内容&#xff0c;本章回中将介绍自定义Radio组件.闲话休提&#xff0c;让我们一起Talk Flutter吧…

LiveGBS流媒体平台GB/T28181功能-操作日志如何配置保留天数过滤记录的日志根据操作名称过滤记录日志

LiveGBS功能操作日志菜单如何配置保留天数过滤记录的日志根据操作名称过滤记录日志 1、操作日志2、配置保留天数3、配置不记录操作日志3.1、不记录所有3.2、不记录指定操作名称 4、相关问题4.1、级联操作日志筛选 5、搭建GB28181视频直播平台 1、操作日志 LiveGBS操作日志菜单…

【PostgreSQL】在DBeaver中实现序列、函数、视图、触发器设计

【PostgreSQL】在DBeaver中实现序列、函数、触发器、视图设计 基本配置一、序列1.1、序列使用1.1.1、设置字段为主键&#xff0c;数据类型默认整型1.1.2、自定义序列&#xff0c;数据类型自定义 1.2、序列延申1.2.1、理论1.2.2、测试1.2.3、小结 二、函数2.1、SQL直接创建2.1.1…

Git命令+github仓库克隆

Git github Git常用命令 开始 git init #创建仓库 git status #查看仓库的状态 git status -s #简单的查看仓库的状态 git ls-files #查看暂存区的内容 git reflog #查看操作的历史记录 暂存区 git add git add <file&g…

NSIS 生成安装包如何导入文件夹的问题

在制作自己的小工具的时候&#xff0c;需将自己的程序生成一个安装包 这里是需要的文件目录config &#xff0c;和主文件的文件目录dist 进行脚本编写的时候&#xff0c;需要加上这一句&#xff0c;使打包的软件中包含config文件夹。 Section "MainSection" SEC01Se…

oracle 19c容器数据库数据加载和传输-----SQL*Loader(一)

目录 数据加载 &#xff08;一&#xff09;控制文件加载 1.创建用户执行sqlldr 2.创建文本文件和控制文件 3.查看表数据 4.查看log文件 &#xff08;二&#xff09;快捷方式加载 1.system用户执行 2.查看表数据 3.查看log文件 外部表 数据加载和传输的工具&#xff1…

typora好看的颜色主题包

typora好看的颜色主题包 一、base.user.css二、orangeheart.css三、插入文件 一、base.user.css h1, h2, h3, h4, strong {font-weight: 600; }#write {counter-reset: h2; }h1 {counter-reset: h2; }h2 {counter-reset: h3; }h3 {counter-reset: h4; }h4 {counter-reset: h5; …

【Java 设计模式】设计原则

文章目录 ✨单一职责原则&#xff08;SRP&#xff09;✨开放/封闭原则&#xff08;OCP&#xff09;✨里氏替换原则&#xff08;LSP&#xff09;✨依赖倒置原则&#xff08;DIP&#xff09;✨接口隔离原则&#xff08;ISP&#xff09;✨合成/聚合复用原则&#xff08;CARP&#…

Spring学习 基于注解的AOP控制事务

8.1.拷贝上一章代码 8.2.applicationContext.xml <!-- 开启spring对注解事务的支持 --> <tx:annotation-driven transaction-manager"transactionManager"/> 8.3.service Service Transactional(readOnlytrue,propagation Propagation.SUPPORTS) publi…

sentinel入门,转载的,不记得在哪复制的了

sentinel 基本概念 开发的原因&#xff0c;需要对吞吐量&#xff08;TPS&#xff09;、QPS、并发数、响应时间&#xff08;RT&#xff09;几个概念做下了解&#xff0c;查自百度百科&#xff0c;记录如下&#xff1a; 响应时间(RT)   响应时间是指系统对请求作出响应的时间。…

049.Python包和模块_虚拟环境超详细讲解

我 的 个 人 主 页&#xff1a;&#x1f449;&#x1f449; 失心疯的个人主页 &#x1f448;&#x1f448; 入 门 教 程 推 荐 &#xff1a;&#x1f449;&#x1f449; Python零基础入门教程合集 &#x1f448;&#x1f448; 虚 拟 环 境 搭 建 &#xff1a;&#x1f449;&…