494.Target Sum

25 年 8 月 5 日 星期二
528 字
3 分钟

0-1 背包问题

Screenshot 2025-08-05 at 10.53.11 pm
Screenshot 2025-08-05 at 11.07.53 pm
Screenshot 2025-08-05 at 10.56.21 pm

memo dfs

python
class Solution:
    def findTargetSumWays(self, nums: List[int], target: int) -> int:
        # p: sum of positive
        # n: sum of negative n = s-p
        # s: sum of nums
        # p = s - n
        # p - (s-p) = t
        # 2p - s = t
        # p = (s+t) / 2
        # let x = s+t
        # Then the question is finding a list of positive number which sum is x / 2
        x = target + sum(nums)
        if x < 0 or x % 2:
            return 0
        p = x / 2
        # 0-1 knapsack
        @cache
        def dfs(i, c):
            if i < 0:
                return 1 if c == 0 else 0
            # 只能不选
            if c < nums[i]:
                return dfs(i-1,c)
            return dfs(i-1, c-nums[i]) + dfs(i-1, c)
        return dfs(len(nums) - 1, p)

dp

image-20250805234950349

不应改为w[i+1]:f[i+1]决定的是第i个数字是否被选择,比如f[2][c]考虑的是下标0到1的w数组,如果改为w[i+1]则遍历i从0到n-1的时候数组会越界,w[n]超出输入数组范围了

为什么是target+1: 从 0 到 target 一共 target+1 个数

python
class Solution:
    def findTargetSumWays(self, nums: List[int], target: int) -> int:
        # p: sum of positive
        # n: sum of negative n = s-p
        # s: sum of nums
        # p = s - n
        # p - (s-p) = t
        # 2p - s = t
        # p = (s+t) / 2
        # let x = s+t
        # Then the question is finding a list of positive number which sum is x / 2


        # x = target + sum(nums)
        # if x < 0 or x % 2:
        #     return 0
        # p = x / 2
        # # 0-1 knapsack
        # @cache
        # def dfs(i, c):
        #     if i < 0:
        #         return 1 if c == 0 else 0
        #     # 只能不选
        #     if c < nums[i]:
        #         return dfs(i-1,c)
        #     return dfs(i-1, c-nums[i]) + dfs(i-1, c)
        # return dfs(len(nums) - 1, p)

        # recurrence
        # (dfs(i) =) dfs(i-1, c-nums[i]) + dfs(i-1, c)
        # f[i] = f[i-1, c-nums[i]] + f[i-1, c]
        # f[i+1] = f[i, c-nums[i]] + f[i, c]

        # i < 0 也进递归了 有 [-1, n-1] (n+1)个递归高度
        # [0, p] 一共 p+1个数
        n = len(nums)
        x = target + sum(nums)
        if x < 0 or x % 2:
            return 0
        p = x // 2
        f = [[0] * (p+1) for _ in range(n+1)]
        f[0][0] = 1 # ( i == 0 and c == 0 时为 1)
        for i, x in enumerate(nums):
            for c in range(p+1): # p 要包括进去
                if c < nums[i]:
                    # if c < nums[i]:
                    #     return dfs(i-1,c)
                    # 这里从 topdown到downtop变为'+'
                    f[i+1][c] = f[i][c]
                else:
                    f[i+1][c] = f[i][c-nums[i]] + f[i][c]
        return f[n][p]
Screenshot 2025-08-06 at 12.38.03 am

文章标题:494.Target Sum

文章作者:Sirui Chen

文章链接:https://blog.siruichen.me/posts/494target_sum[复制]

最后修改时间:


商业转载请联系站长获得授权,非商业转载请注明本文出处及文章链接,您可以自由地在任何媒体以任何形式复制和分发作品,也可以修改和创作,但是分发衍生作品时必须采用相同的许可协议。
本文采用CC BY-NC-SA 4.0进行许可。