原题: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 = 3There are 5 ways to assign symbols to make the sum of nums be target 3.
Note:
- The length of the given array is positive and will not exceed 20.
- The sum of elements in the given array will not exceed 1000.
- 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)