494. Target Sum
494. 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. 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. https://www.youtube.com/watch?v=r6Wz4W1TbuI https://leetcode.com/problems/target-sum/solution/ https://zxi.mytechroad.com/blog/dynamic-programming/leetcode-494-target-sum/ Approach #1 Brute Force [Accepted] Algorithm The brute force approach is based on recursion. We need to try to put both the + and - symbols at every location in the given public class Solution { int count = 0; public int findTargetSumWays(int[] nums, int S) { calculate(nums, 0, 0, S); return count; } public void calculate(int[] nums, int i, int sum, int S) { if (i == nums.length) { if (sum == S) count++; } else { calculate(nums, i + 1, sum + nums[i], S); calculate(nums, i + 1, sum - nums[i], S); } } } Approach #2 Recursion with memoization [Accepted] Algorithm It can be easily observed that in the last approach, a lot of redundant function calls could be made with the same value of i as the current index and the same value of sum as the current sum, since the same values could be obtained through multiple paths in the recursion tree. In order to remove this redundancy, we make use of memoization as well to store the results which have been calculated earlier. public class Solution { int count = 0; public int findTargetSumWays(int[] nums, int S) { int[][] memo = new int[nums.length][2001]; for (int[] row: memo) Arrays.fill(row, Integer.MIN_VALUE); return calculate(nums, 0, 0, S, memo); } public int calculate(int[] nums, int i, int sum, int S, int[][] memo) { if (i == nums.length) { if (sum == S) return 1; else return 0; } else { if (memo[i][sum + 1000] != Integer.MIN_VALUE) { return memo[i][sum + 1000]; } int add = calculate(nums, i + 1, sum + nums[i], S, memo); int subtract = calculate(nums, i + 1, sum - nums[i], S, memo); memo[i][sum + 1000] = add + subtract; return memo[i][sum + 1000]; } } } Approach #3 2D Dynamic Programming public class Solution { public int findTargetSumWays(int[] nums, int S) { int[][] dp = new int[nums.length][2001]; dp[0][nums[0] + 1000] = 1; dp[0][-nums[0] + 1000] += 1; for (int i = 1; i < nums.length; i++) { for (int sum = -1000; sum <= 1000; sum++) { if (dp[i - 1][sum + 1000] > 0) { dp[i][sum + nums[i] + 1000] += dp[i - 1][sum + 1000]; dp[i][sum - nums[i] + 1000] += dp[i - 1][sum + 1000]; } } } return S > 1000 ? 0 : dp[nums.length - 1][S + 1000]; } } Approach #4 1D Dynamic Programming public class Solution { public int findTargetSumWays(int[] nums, int S) { int[] dp = new int[2001]; dp[nums[0] + 1000] = 1; dp[-nums[0] + 1000] += 1; for (int i = 1; i < nums.length; i++) { int[] next = new int[2001]; for (int sum = -1000; sum <= 1000; sum++) { if (dp[sum + 1000] > 0) { next[sum + nums[i] + 1000] += dp[sum + 1000]; next[sum - nums[i] + 1000] += dp[sum + 1000]; } } dp = next; } return S > 1000 ? 0 : dp[S + 1000]; } }
posted on 2018-08-09 18:41 猪猪🐷 阅读(152) 评论(0) 收藏 举报
浙公网安备 33010602011771号