zoukankan      html  css  js  c++  java
  • [Leetcode] DP -- Target Sum

    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.

    Find out how many ways to assign symbols to make sum of integers equal to target S.

    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.

    Solution:
     
    1st use  DFS recursive,  like a binary tree;   Go to left (+1) or right (-1); then  when sum is S  go the upper next。
    But it is TLE in python

     

     1     count = 0
     2     def findTargetSumWays(self, nums, S):
     3         def findTargetHelper(nums, index, S):
     4             if index == len(nums):
     5                 if S == 0:
     6                     self.count = self.count + 1
     7                 return
     8              
     9         
    10             findTargetHelper(nums, index+1, S - nums[index])         #+1
    11             findTargetHelper(nums, index+1, S + nums[index])         #-1
    12         
    13         findTargetHelper(nums, 0, S)
    14 
    15         return self.count
    2.   DP
    Refer to the other's idea that I didn't came up with .   
    this problem could be transferred to subset sum problem (similar to knapback problem)
    if there exist a solution,
    P: positive number subset;     N: positive number subset
     then sum(P) - sum(N)  = S;               |P| + |N| = len(nums)
    so  sum(P) + sum(N) + sum(P) - sum(N) =  S + sum(P) + sum(N)
             2*sum(P) = S + sum(nums)
                sum(P) = (S + sum(nums))/2
     the original problem  has been changed to a subset sum problem: :
    Find a subset P of nums such that sum(P) = (target + sum(nums)) / 2
     
     1         def subsetSum(nums, target):
     2             dp = [0]*(target+1)
     3             dp[0] = 1
     4             for num in nums:
     5                 for j in range(target, num-1, -1):
     6                     dp[j] += dp[j-num]
     7                     #print ("dp: ", target, j, dp[j])
     8             return dp[target]
     9             
    10         sumN = sum(nums)
    11         
    12         if sumN < S or (S+sumN) %2 != 0:
    13             return 0
    14         return subsetSum(nums, (S+sumN)>>1)
  • 相关阅读:
    Pocket Cube
    善意的投票(最大流)
    清明梦超能力者黄YY(idx数组)
    Inside Triangle
    孤岛营救问题(BFS+状压DP)
    餐巾计划问题(费用流)
    Lunch Time(费用流变型题,以时间为费用)
    71. Simplify Path
    70. Climbing Stairs
    69. Sqrt(x)
  • 原文地址:https://www.cnblogs.com/anxin6699/p/7078424.html
Copyright © 2011-2022 走看看