📅  最后修改于: 2023-12-03 15:11:40.461000             🧑  作者: Mango
给定一个由数字组成的数组和一个目标数字S,现在需要从数组中选出一些数字,并使它们的和等于S。如果可以找到这样的数字,输出需要选出的数字的最小个数,否则输出-1。
例如:给定数组[2,3,1,4,2]和目标数字S为7,需要从数组中选出数字2、3、2使它们的和等于7,因此输出3。
这个问题可以通过动态规划来解决。具体来说,我们可以定义一个二维数组dp,其中dp[i][j]表示从数组的前i个数字中选出一些数字使它们的和等于j所需的最小数字个数。显然,当j=0时,我们可以选择不选任何数字,因此dp[i][0]=0;当i=0时,因为数组为空,不可能选出任何数字,因此dp[0][j]=无穷大。
对于每个数字nums[i],我们有两个选择:选它或不选它。如果我们选择不选它,那么dp[i][j]=dp[i-1][j];如果我们选择选它,那么dp[i][j]=dp[i-1][j-nums[i]]+1。我们选取这两种方法中的较小值作为dp[i][j]的值,即
dp[i][j] = min(dp[i-1][j], dp[i-1][j-nums[i]]+1)
最终,当dp[n][S]为无穷大时,说明从数组中无法选出数字使它们的和等于S,输出-1,否则输出dp[n][S]即为需要选出的数字的最小个数。
def findMinNum(nums, S):
n = len(nums)
dp = [[float('inf') if j > 0 else 0 for j in range(S+1)] for i in range(n+1)]
for i in range(1, n+1):
for j in range(1, S+1):
if nums[i-1] <= j:
dp[i][j] = min(dp[i-1][j], dp[i-1][j-nums[i-1]]+1)
else:
dp[i][j] = dp[i-1][j]
return dp[n][S] if dp[n][S] != float('inf') else -1
输入:nums=[2,3,1,4,2], S=7;输出:3。
输入:nums=[1,2,3,4,5], S=10;输出:2。
输入:nums=[1,1,1,1,1], S=6;输出:6。
由于在二维数组dp中,我们需要计算dp[i][j]的值时都需要遍历前面所有的数字,因此总时间复杂度为O(nS)。