此类问题与传统的01背包问题稍有不同,尤其是状态转移方程。01背包问题会有max(),求一个最大;而此问题求的是能有多少种方法,面对第i个元素,存在取与不取的问题,最后加起来就是所有的方法。
class Solution(object):
def findTargetSumWays(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
# 这个题问的是有多少种方法,跟01背包还有点不同,01背包求最大,会有max()
# 假设所有前面是‘+’的整数和为P,前面是‘-’的整数和为N
# 则P+N=SUM,P-N=target,两式可得P=(SUM+target)/2,SUM和target都是可以计算得到的固定值
# 此时可以将问题转化为01背包问题:
# dp[i][j]:在数组nums前i个数字种选取元素,使这些元素之和等于j的方案数。
# 首先分析特殊情况:nums为整数数组,所以P肯定为整数,则(SUM+target)/2为整数,也就是(SUM+target)能被2整除,如果不能被2整除就是有问题。再一个如果target的绝对值大于sum也肯定是有问题
# 状态转移方程:
# 1.当nums[i] > j 时,dp[i][j]=dp[i-1][j]
# 2.当nums[i] <= j 时,可以选择是否取nums[i]
# 不取nums[i]:dp[i][j]=dp[i-1][j]
# 取num[i]:dp[i][j]=dp[i-1][j-nums[i]]
# 所以2的dp[i][j]应该是两者的相加,因为我们求得是由多少种方法
# 因此,dp[i][j]=dp[i-1][j]+dp[i-1][j-nums[i]]
# 初始化:
# dp[0][0]=1,没有任何元素可以选择时,和只能为0
# dp[0][j]=0,j>0
# 遍历顺序,01背包问题都是先物品,后背包,此时应为先元素,后和
sum_ = sum(nums)
# 前面是‘+’的整数和
sump = (sum_+target)/2
if abs(target)>sum_ or (sum_+target) % 2 == 1:
return 0
dp = [[0 for _ in range(sump+1)] for _ in range(len(nums)+1)]
# 初始化,j为0,不管是否有元素,都只有一种方法就是
for i in range(len(nums)+1):
dp[i][0]=1
for i in range(1, len(nums)+1):
for j in range(sump+1):
if j >= nums[i-1]:
dp[i][j] = dp[i-1][j] + dp[i-1][j-nums[i-1]]
else:
dp[i][j] = dp[i-1][j]
return dp[-1][-1]
class Solution(object):
def findTargetSumWays(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
# 优化,使用数组解决
sum_ = sum(nums)
# 前面是‘+’的整数和
sump = (sum_+target)/2
if abs(target)>sum_ or (sum_+target) % 2 == 1:
return 0
dp = [0 for _ in range(sump+1)]
# 装满容量为0的背包,有1种方法,就是装0件物品
dp[0] = 1
for i in range(1, len(nums)+1):
for j in range(sump, -1, -1):
if j >= nums[i-1]:
dp[j] = dp[j] + dp[j-nums[i-1]]
return dp[-1]
class Solution {
int count = 0;
public int findTargetSumWays(int[] nums, int target) {
backtrack(nums, target, 0, 0);
return count;
}
public void backtrack(int[] nums, int target, int index, int sum) {
if (index == nums.length) {
if (sum == target) {
count++;
}
} else {
backtrack(nums, target, index + 1, sum + nums[index]);
backtrack(nums, target, index + 1, sum - nums[index]);
}
}
}
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/target-sum/solution/mu-biao-he-by-leetcode-solution-o0cp/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。