Vison's Blog
所有文章
文章总览
编辑器
Publications
About Me
Search
目录
#toc-container
下载Markdown文件
【4.24】LeetCode每日一题· 组合总和 Ⅳ
2021年04月24日 12时13分
标签:
LeetCode
动态规划
## 题目描述 给你一个由 不同 整数组成的数组 nums ,和一个目标整数 target 。请你从 nums 中找出并返回总和为 target 的元素组合的个数。 题目数据保证答案符合 32 位整数范围。 #### 示例1 ``` 输入:nums = [1,2,3], target = 4 输出:7 解释: 所有可能的组合为: (1, 1, 1, 1) (1, 1, 2) (1, 2, 1) (1, 3) (2, 1, 1) (2, 2) (3, 1) 请注意,顺序不同的序列被视作不同的组合。 ``` #### 示例2 ``` 输入:nums = [9], target = 3 输出:0 ``` #### 提示 ``` 1 <= nums.length <= 200 1 <= nums[i] <= 1000 nums 中的所有元素 互不相同 1 <= target <= 1000 ``` #### 来源 > 来源:力扣(LeetCode) > 链接:[题目链接](https://leetcode-cn.com/problems/combination-sum-iv "题目链接") ## 解题思路 一个简单的动态规划题,可以先从递归考虑:组成`target`,可以将其分解成从`nums`中选择一个数`num`,然后组成`target-num`;因此组成`target`的组合数就是遍历`num`,组成`target-num`的组合数之和。 然后将递归参数`target`转变成动态规划状态的参数即可,可以容易得出状态转移方程。注意需要注意边界条件:组成数0的组合数为1。 另外需要注意的一点是:由于答案在32位整数范围内因此如果dp表格记录的数组超过32位整数范围的话,是不可能用到这些数的。本身让其自然溢出即可,但是LeetCode对于自然溢出会判定为runtime error.....(一言难尽),所以在状态转移的时候把答案模上(`1ll<<32`)即可。 这两天LeetCode每日一题都是动态规划题,让我对DP也有了更深的理解。实际上DP和递归类似(但是DP求解的问题一定没有重叠的子问题),如果可以使用记忆化搜索实现DP,就可以考虑将记忆化搜索中的参数作为DP表格的行、列参数设计状态,然后推出状态转移方程。实际上DP可以说是DFS的扩展或可以优化的特例。 ## 代码 ```cpp class Solution { public: // dp[i] := 使用nums数组中的不同整数组成数字i的方法数 // 状态转移方程:dp[i] = sum{dp[i-num]} if num <= i for num in nums // 边界条件:dp[0] = 1 int combinationSum4(vector
& nums, int target) { long long dp[target+1]; dp[0] = 1; for(int i = 1; i <= target; i++){ dp[i] = 0; for(int& num: nums){ if(num <= i){ dp[i] = (dp[i] + dp[i-num]) % (1ll<<32); } } } return dp[target]; } }; ``` ### 用时和内存 > 执行用时:0 ms,在所有 C++提交中击败了100.00%的用户 > 内存消耗:6.5 MB,在所有 C++提交中击败了76.83%的用户
所有评论
暂无评论
新增评论
评论
邮箱
邮箱仅作验证使用
图形验证码
邮箱验证码
发送验证码
发表评论
所有评论
暂无评论