diff --git a/solutions/377. Combination Sum IV.md b/solutions/377. Combination Sum IV.md new file mode 100644 index 0000000..901f5de --- /dev/null +++ b/solutions/377. Combination Sum IV.md @@ -0,0 +1,44 @@ +# [377. Combination Sum IV](https://leetcode.com/problems/combination-sum-iv/) + +# 思路 + +给定一个元素各不相同的数组和一个整数target,从数组从选取(可重复选)若干个数使和为target,问有多少种选法,注意一个排列就算一种选法,例如[1,2]和[2,1]是两种选法。 + +由于要求选法数,所以很容易想到用动态规划来求解,设 +``` +dp[i]表示target为i时的选法数(初始为0), dp[0] = 1 +``` +即dp[target]为所求。 + +转态转移方程也很简单,就是每次都遍历一遍给定的数组nums然后不断累加: +``` +for all num in nums: + dp[i] += dp[i - num]; +``` + +所以时间复杂度为O(n*target),空间复杂度为O(target)。 + +> 注意此题每个排列就算一种选法,例如[1,2]和[2,1]是两种选法,如果只算一次话那就是一个完全背包问题,可参考[我的博客-动态规划之背包问题系列](https://tangshusen.me/2019/11/24/knapsack-problem/)。 + +# C++ +``` C++ +class Solution { +public: + int combinationSum4(vector& nums, int target) { + int n = nums.size(); + vectordp(target+1, 0); + dp[0] = 1; + for(int i = 1; i <= target; i++){ + for(int &num: nums){ + if(i >= num){ + // 防止超过INT_MAX溢出 + if(dp[i] <= INT_MAX - dp[i - num]) + dp[i] += dp[i - num]; + else dp[i] = INT_MAX; + } + } + } + return dp[target]; + } +}; +```