LeetCode 494. Target Sum

原题:https://leetcode.com/problems/target-sum/description/


题目描述:
You are given a list of non-negative integers, a1, a2, …, an, and a target, S. Now you have 2 symbols + and -. For each integer, you should choose one from + and - as its new symbol.

Example 1:

Input: nums is [1, 1, 1, 1, 1], S is 3.
Output: 5 Explanation:

-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

There are 5 ways to assign symbols to make the sum of nums be target 3.

Note:

  1. The length of the given array is positive and will not exceed 20.
  2. The sum of elements in the given array will not exceed 1000.
  3. Your output answer is guaranteed to be fitted in a 32-bit integer.

这道题有两种解法,深度优先搜索和动态规划。我第一反应是深度优先搜索的递归形式,但是TLE,然后发现可以用缓存节省时间。
将每一个数看作一个节点,下一个数前面加’+’或’-‘分别表示该节点的左右儿子。然后就是通过递归遍历。但是递归的时间复杂度很高,我尝试用非递归的DFS,但是如何存储当前累加值这一点比较难实现,所以选择用缓存减少递归中重复的操作。将每种已经得到的结果保存起来,在递归过程中,每次查询缓存是否已经包含当前要求的值。
这种方法可以解决问题但效率还是有点低。


深度优先搜索加缓存

class Solution(object):

    def findTargetSumWays(self, nums, S):
        if nums is None or len(nums) == 0:
            return 0
        memo = {}
        def sums(i, s):
            if (i, s) not in memo:
                memo[(i, s)] = 0
                if i == len(nums):
                    if s == S:
                        memo[(i, s)] = 1
                else:
                    memo[(i, s)] = sums(i+1, s + nums[i])+sums(i+1, s - nums[i])
            return memo[(i, s)]

        return sums(0, 0)

139 / 139 test cases passed.
Status: Accepted
Runtime: 758 ms


class Solution(object):
    def findTargetSumWays(self, nums, S):
        if not nums:
            return 0
        dic = {nums[0]: 1, -nums[0]: 1} if nums[0] != 0 else {0: 2}
        for i in range(1, len(nums)):
            tmp = {}
            for d in dic:
                tmp[d + nums[i]] = tmp.get(d + nums[i], 0) + dic.get(d, 0)
                tmp[d - nums[i]] = tmp.get(d - nums[i], 0) + dic.get(d, 0)
            dic = tmp
        return dic.get(S, 0)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值