题目:
给你一个由 不同 整数组成的数组 nums
,和一个目标整数 target
。请你从 nums
中找出并返回总和为 target
的元素组合的个数。
题目数据保证答案符合 32 位整数范围。
提示:
1 <= nums.length <= 200
1 <= nums[i] <= 1000
nums
中的所有元素 互不相同1 <= target <= 1000
思考:
又是前两天的题目的姊妹题,一开始试图用类似的方法写代码,如下:
class Solution(object):
def combinationSum4(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
n = len(nums)
def makeTree(target, nums):
if target < 0:
return 0
elif target == 0:
return 1
else:
ans = 0
for index in range(0, n):
ans += makeTree(target - nums[index], nums)
return ans
return makeTree(target, nums)
虽然是对的,但是超时了:
思考了一下,发现这道题可以用动态规划做。
优化:动态规划:
用dp[i]表示和为i的组合个数,i的范围是[nums的最小值, target],最终dp[target]即为题目所求,算法如下:
- 将nums数组从小到大排序,若 nums的最小值 > target,直接返回0;
- 将dp数组初始化为全0;
- 和为 nums的最小值(即nums[0])的组合个数一定只有1个,所以dp[nums[0]]初始化为1;
- 对每个i,遍历nums中的元素j,,此处注意判断i和j的大小关系(若j>i,当前dp[i]计算完毕,进行下一个i的计算;若j=i,说明有一个组合是只含一个元素j的,dp[i]加一;若j<i,则dp[i] += dp[i-j])
- 返回dp[target]的值
代码如下:
class Solution(object):
def combinationSum4(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
n = len(nums)
nums.sort()
if target < nums[0]:
return 0
dp = [0 for _ in range(target+1)]
dp[nums[0]] = 1
for i in range(nums[0]+1, target+1):
for j in nums:
if j > i:
break
elif j == i:
dp[i] += 1
else:
dp[i] += dp[i-j]
return dp[target]
提交通过: