[leetcode_494]494. 目标和

494. 目标和

难度中等767收藏分享切换为英文接收动态反馈

给你一个整数数组 nums 和一个整数 target

向数组中的每个整数前添加 '+''-' ,然后串联起所有整数,可以构造一个 表达式

  • 例如,nums = [2, 1] ,可以在 2 之前添加 '+' ,在 1 之前添加 '-' ,然后串联起来得到表达式 "+2-1"

返回可以通过上述方法构造的、运算结果等于 target 的不同 表达式 的数目。

示例 1:

输入:nums = [1,1,1,1,1], target = 3
输出:5
解释:一共有 5 种方法让最终目标和为 3 。
-1 + 1 + 1 + 1 + 1 = 3
+1 - 1 + 1 + 1 + 1 = 3
+1 + 1 - 1 + 1 + 1 = 3
+1 + 1 + 1 - 1 + 1 = 3
+1 + 1 + 1 + 1 - 1 = 3

示例 2:

输入:nums = [1], target = 1
输出:1

提示:

  • 1 <= nums.length <= 20
  • 0 <= nums[i] <= 1000
  • 0 <= sum(nums[i]) <= 1000
  • -1000 <= target <= 100

递归解法

解法1   暴力递归 超时了


class Solution:
    def findTargetSumWays(self, nums: List[int], S: int) -> int:
        positive = 0
        negative = 0
        cur_result = []
        level = 0
        self.result = []

        self._generate(nums, S, positive, negative, cur_result, level)
        return len(self.result)
        pass

    def _generate(self, nums: List, target, positive: int, negative: int, cur_result: List, level: int):
        # terminator
        if positive + negative == len(nums):
            if sum(cur_result) == target:
                self.result.append(cur_result.copy())
            return

        # current logic process
        cur_result.append(nums[level])
        # drill down
        self._generate(nums, target, positive + 1, negative, cur_result, level + 1)
        # reverse the current level status
        cur_result.pop(-1)

        # current logic process
        cur_result.append(-nums[level])
        # drill down
        self._generate(nums, target, positive, negative + 1, cur_result, level + 1)
        # reverse the current level status
        cur_result.pop(-1)
        pass

解法2 暴力递归

超时了

class Solution:
    """
    时间复杂度:O(2^n)
    
    """
    def findTargetSumWays(self, nums: List[int], S: int) -> int:
        cur_result = 0
        level = 0
        return self._dfs(nums, cur_result, level, S)

    def _dfs(self, nums: List, cur: int, level, target: int):
        if level == len(nums):
            return 1 if cur == target else 0

        left = self._dfs(nums, cur + nums[level], level + 1, target)
        right = self._dfs(nums, cur - nums[level], level + 1, target)
        return left + right

      

动态规划

img

注意题目中有要求 0< nums[i]<1000 所以这里 可以使用dp 进行求解

dp[i][target] 表示 去前i个元素 构成target的数目

初始化第一个元素
dp[0][target] =1

n = len(nums)
total = sum(nums)
n为nums的长度

dp的维度 row * col = (n+1) * (2*total+1)

状态转义方程:

dp[i+1][j] = dp[i][j-nums[i]] + dp[i][j+ nums[i]]

看下代码 实现:

from typing import List


class Solution:
    """
    https://www.bilibili.com/video/BV1WW411C7Mp/
    """

    def findTargetSumWays(self, nums: List[int], target: int) -> int:

        total = sum(nums)
        # 值范围超过了sum的值范围 则无法得到
        if target > total:
            return 0

        n = len(nums)
        offset = total

        # dp = (n+1) *  (2*total+1)
        dp = [[0] * (2 * total + 1) for _ in range(n + 2)]

        dp[0][offset] = 1

        for i in range(0, n):
            j = nums[i]
            while j < 2 * total + 1 - nums[i]:
                # dp process
                if dp[i][j]:
                    dp[i + 1][j + nums[i]] += dp[i][j]
                    dp[i + 1][j - nums[i]] += dp[i][j]

                j += 1
        return dp[n][offset + target]

参考文档

花花酱 494题解

分享快乐,留住感动. '2021-06-09 21:45:04' --frank
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值