|
| 1 | +# 494. Target Sum |
| 2 | + |
| 3 | +## Recursive Brute Force |
| 4 | +- Runtime: 2^N |
| 5 | +- Space: 2^N |
| 6 | +- N = Number of elements in array |
| 7 | + |
| 8 | +Fairly straight forward, however, will run into time limit exceeded. |
| 9 | +Noticed how the run-time is not big O of 2^N, its because this brute force will always run exactly 2^N times. |
| 10 | + |
| 11 | +``` |
| 12 | +class Solution: |
| 13 | + def findTargetSumWays(self, nums: List[int], S: int) -> int: |
| 14 | + |
| 15 | + def find_sum_ways_helper(nums, curr_sum, start_i): |
| 16 | + if curr_sum == S and start_i >= len(nums): |
| 17 | + return 1 |
| 18 | + elif start_i >= len(nums): |
| 19 | + return 0 |
| 20 | + n_sums = 0 |
| 21 | + n_sums += find_sum_ways_helper(nums, curr_sum + nums[start_i], start_i+1) |
| 22 | + n_sums += find_sum_ways_helper(nums, curr_sum - nums[start_i], start_i+1) |
| 23 | + return n_sums |
| 24 | + |
| 25 | + return find_sum_ways_helper(nums, 0, 0) |
| 26 | +``` |
| 27 | + |
| 28 | +## Iterative Solution with Map |
| 29 | +- Runtime: O(N*U) |
| 30 | +- Space: O(U) |
| 31 | +- N = Number of elements in array |
| 32 | +- U = Number of unique sums (Worst case U=2^N) |
| 33 | + |
| 34 | +We can use a dictionary to keep track of the sums and how many paths there are for each sum. |
| 35 | +We just need to maintain a rolling dictionary as we traverse across the numbers. |
| 36 | +Each traversal we will create new sums and add them into a new dictionary. |
| 37 | +We will move the values across from the old dictionary as well. |
| 38 | + |
| 39 | +For the run-time, U can be 2^N for the worst case (2,4,8,16,32...). |
| 40 | +Now, you may think this is solution is terrible compared to the previous recursive solution. |
| 41 | +That maybe true but only if we were to always create a unique sum every single time. |
| 42 | +Maybe an input like [1,10,100,1000,10000...] |
| 43 | +However, given any other input, since its add and subtract and not multiply or divide, its unlikely and its more likely we will have overlapping sums. |
| 44 | +So U is actually less than O(2^N) on most cases while the brute force solution above will always be run at 2^N. |
| 45 | + |
| 46 | +``` |
| 47 | +from collections import defaultdict |
| 48 | +
|
| 49 | +class Solution: |
| 50 | + def findTargetSumWays(self, nums: List[int], S: int) -> int: |
| 51 | + if len(nums) == 0: |
| 52 | + return 0 |
| 53 | + sum_to_n_paths = defaultdict(int) |
| 54 | + sum_to_n_paths[nums[0]] += 1 |
| 55 | + sum_to_n_paths[-nums[0]] += 1 |
| 56 | + for n in nums[1:]: |
| 57 | + new_sum_map = defaultdict(int) |
| 58 | + for key, val in sum_to_n_paths.items(): # carry over paths |
| 59 | + new_sum_map[key+n] += val |
| 60 | + new_sum_map[key-n] += val |
| 61 | + sum_to_n_paths = new_sum_map |
| 62 | + return sum_to_n_paths[S] |
| 63 | +``` |
0 commit comments