Skip to content

Latest commit

 

History

History
44 lines (37 loc) · 1.84 KB

64. 目标和.md

File metadata and controls

44 lines (37 loc) · 1.84 KB

给定一个非负整数数组,a1, a2, ..., an, 和一个目标数,S。现在你有两个符号 + 和 -。对于数组中的任意一个整数,你都可以从 + 或 -中选择一个符号添加在前面。返回可以使最终数组和为目标数 S 的所有添加符号的方法数。

原问题等同于: 找到nums一个正子集和一个负子集,使得总和等于target
我们假设P是正子集,N是负子集 例如: 假设nums = [1, 2, 3, 4, 5],target = 3,一个可能的解决方案是+1-2+3-4+5 = 3 这里正子集P = [1, 3, 5]和负子集N = [2, 4]
那么让我们看看如何将其转换为子集求和问题:
sum(P) - sum(N) = target
sum(P) + sum(N) + sum(P) - sum(N) = target + sum(P) + sum(N)
2 * sum(P) = target + sum(nums)
因此,原来的问题已转化为一个求子集的和问题: 找到nums的一个子集 P,使得sum(P) = (target + sum(nums)) / 2
请注意,上面的公式已经证明target + sum(nums)必须是偶数,否则输出为0

dp[ i ][ j ]定义为从数组nums中 0 - i 的元素进行取舍可以得到 j 的方法数量
class Solution(object):
    def findTargetSumWays(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        sumAll = sum(nums)
        if target > sumAll or (target + sumAll) % 2:
            return 0
        target = (target + sumAll) // 2

        dp = [[0]*(target+1) for _ in range(len(nums))]
        dp[0][0] = 2 if nums[0] == 0 else 1

        for j in range(1, target+1):
            if j==nums[0]:
                dp[0][j] = 1
        

        for i in range(1, len(nums)):
            for j in range(target+1):
                if j-nums[i] >= 0:
                    dp[i][j] = dp[i-1][j]+dp[i-1][j-nums[i]]
                else:
                    dp[i][j] = dp[i-1][j]
        return dp[-1][-1]