leetcode494.目标和

1.题目描述

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

返回可以使最终数组和为目标数 S 的所有添加符号的方法数。

示例 1:

输入: nums: [1, 1, 1, 1, 1], S: 3
输出: 5
解释: 

-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

一共有5种方法让最终目标和为3。
注意:

数组非空,且长度不会超过20。
初始的数组的和不会超过1000。
保证返回的最终结果能被32位整数存下。

2.解题思路

方案一:dfs+剪枝

里先给出用DFS+记忆化+剪枝的方法:

直接使用DFS会超时,要做一些优化,使用dp字典来记录在遍历到第i个元素和为sum(即,字典键为(i,sum))时,满足数组所有数值和为S的个数(即,字典值为cnt)。

leetcode494.目标和_第1张图片

假设nums中有4个数,target =2,返回4

在每一行中,假设目标值曾经出现过,那就不用再算了,比如说橘黄色的第二个0出现时,由于之前0出现过,这个就不用再分解了,因为后续是重复的操作

方案二:动态规划

思路后续会给出

3.代码实现

方案一:


class Solution(object):     
    def findTargetSumWays(self, nums, S):
        """
        :type nums: List[int]
        :type S: int
        :rtype: int
        """
        if not nums:
            return 0
        dp = {}
        res = self.helper(nums, S, 0, 0, dp)
        return res

    def helper(self, nums, S, i, sum, dp):
        if i == len(nums):
            return S == sum
        if i < len(nums) and (i, sum) in dp:
            return dp.get((i, sum))
        if i < len(nums) and (i, sum) not in dp:
            cnt1 = self.helper(nums, S, i+1, sum+nums[i], dp)
            cnt2 = self.helper(nums, S, i+1, sum-nums[i], dp)
            dp[(i, sum)] = cnt1 + cnt2
            return dp.get((i, sum))

 

方案二:后续给出

你可能感兴趣的:(leetcode)