LeetCode-494. Target Sum (JAVA) (目标和)
来源:互联网 发布:mysql 断电 无法启动 编辑:程序博客网 时间:2024/06/05 13:21
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: 5Explanation: -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.
目标和
刚开始想到用之前的df0s但是超时
public int findTargetSumWays(int[] nums, int S) {if (nums == null || nums.length == 0)return 0;int res[] = new int[1];dfsCore(nums, 0, 0, 0, S, res);return res[0];}private void dfsCore(int[] nums, int sum, int idx, int k, int target, int[] res) {if (k == nums.length) {if (sum == target)res[0] += 1;return;}for (int i = idx; i < nums.length; i++) {dfsCore(nums, sum + nums[i], i + 1, k + 1, target, res);dfsCore(nums, sum - nums[i], i + 1, k + 1, target, res);}}之后找到解决方法,因为多用了for循环,导致超时
public int findTargetSumWays(int[] nums, int S) {int[] arr = new int[1];helper(nums, S, arr, 0, 0);return arr[0];}public void helper(int[] nums, int S, int[] arr, int sum, int start) {if (start == nums.length) {if (sum == S) {arr[0]++;}return;}// 这里千万不要加for循环,因为我们只是从index0开始helper(nums, S, arr, sum - nums[start], start + 1);helper(nums, S, arr, sum + nums[start], start + 1);}
public class Solution {public int findTargetSumWays(int[] nums, int S) {if (nums == null || nums.length == 0) {return 0;}return helper(nums, S, 0, 0, 0);}// 这里不传入全局变量count的原因是每次的count都已返回值形式返回public int helper(int[] nums, int S, int sum, int index, int count) {if (index == nums.length) {if (sum == S) {count++;}return count;}return helper(nums, S, sum + nums[index], index + 1, count)+ helper(nums, S, sum - nums[index], index + 1, count);}}
记忆化搜索算法
来源discuss:https://discuss.leetcode.com/topic/76245/java-simple-dfs-with-memorization
public class Solution {public int findTargetSumWays(int[] nums, int S) {if (nums == null || nums.length == 0) {return 0;}return helper(nums, 0, 0, S, new HashMap<>());}private int helper(int[] nums, int index, int sum, int S, Map<String, Integer> map) {// 避免数字是重复,无法找到截断点String encodeString = index + "->" + sum;if (map.containsKey(encodeString)) {return map.get(encodeString);}if (index == nums.length) {if (sum == S) {return 1;} else {return 0;}}int curNum = nums[index];int add = helper(nums, index + 1, sum - curNum, S, map);int minus = helper(nums, index + 1, sum + curNum, S, map);map.put(encodeString, add + minus);return add + minus;}}
最终版DP
来源http://blog.csdn.net/hit0803107/article/details/54894227
【问题分析】
1、该问题求解数组中数字只和等于目标值的方案个数,每个数字的符号可以为正或负(减整数等于加负数)。
2、该问题和矩阵链乘很相似,是典型的动态规划问题
3、举例说明: nums = {1,2,3,4,5}, target=3, 一种可行的方案是+1-2+3-4+5 = 3
该方案中数组元素可以分为两组,一组是数字符号为正(P={1,3,5}),另一组数字符号为负(N={2,4})
因此: sum(1,3,5) - sum(2,4) = target
sum(1,3,5) - sum(2,4) + sum(1,3,5) + sum(2,4) = target + sum(1,3,5) + sum(2,4)
2sum(1,3,5) = target + sum(1,3,5) + sum(2,4)
2sum(P) = target + sum(nums)
sum(P) = (target + sum(nums)) / 2
由于target和sum(nums)是固定值,因此原始问题转化为求解nums中子集的和等于sum(P)的方案个数问题
4、求解nums中子集合只和为sum(P)的方案个数(nums中所有元素都是非负)
该问题可以通过动态规划算法求解
举例说明:给定集合nums={1,2,3,4,5}, 求解子集,使子集中元素之和等于9 = new_target = sum(P) = (target+sum(nums))/2
定义dp[10]数组, dp[10] = {1,0,0,0,0,0,0,0,0,0}
dp[i]表示子集合元素之和等于当前目标值的方案个数, 当前目标值等于9减去当前元素值
当前元素等于1时,dp[9] = dp[9] + dp[9-1]
dp[8] = dp[8] + dp[8-1]
...
dp[1] = dp[1] + dp[1-1]
当前元素等于2时,dp[9] = dp[9] + dp[9-2]
dp[8] = dp[8] + dp[8-2]
...
dp[2] = dp[2] + dp[2-2]
当前元素等于3时,dp[9] = dp[9] + dp[9-3]
dp[8] = dp[8] + dp[8-3]
...
dp[3] = dp[3] + dp[3-3]
当前元素等于4时,
...
当前元素等于5时,
...
dp[5] = dp[5] + dp[5-5]
最后返回dp[9]即是所求的解
public class Solution {public int findTargetSumWays(int[] nums, int S) {int sum = 0;for (int i = 0; i < nums.length; i++) {sum += nums[i];}if (S > sum || (sum + S) % 2 == 1)return 0;return subsetSum(nums, (sum + S) / 2);}private int subsetSum(int[] nums, int S) {int[] dp = new int[S + 1];dp[0] = 1;//C(0,0)=1for (int i = 0; i < nums.length; i++) {for (int j = S; j >= nums[i]; j--) {dp[j] += dp[j - nums[i]];}}return dp[S];}}
- LeetCode-494. Target Sum (JAVA) (目标和)
- LeetCode 494. Target Sum
- [LeetCode]494. Target Sum
- [leetcode]494. Target Sum
- Leetcode 494. Target Sum
- Leetcode-494. Target Sum
- Leetcode 494. Target Sum
- leetcode-494. Target Sum
- leetcode:494. Target Sum
- (LeetCode) 494. Target Sum
- LeetCode 494. Target Sum
- leetcode 494. Target Sum
- LeetCode 494. Target Sum
- LeetCode 494. Target Sum
- LeetCode 494. Target Sum
- [leetcode] 494. Target Sum
- [LeetCode] 494. Target Sum
- LeetCode笔记:494. Target Sum
- FullCalendar – jQuery Event Calendar in ASP.NET
- cc2540 usb hid升级
- 电子元件的学习
- 算法导论 RandomizedSelect
- 函数在实现过程内存中的压栈和出栈
- LeetCode-494. Target Sum (JAVA) (目标和)
- HDU 4675
- 矩阵的加法、减法、乘法、转置
- spring 获取上下文applicationContext
- [BZOJ 1207][HNOI2004]打鼹鼠:DP
- 动态规划练习一—14怪盗基德的滑翔翼
- 浅谈 Java 字符串(String, StringBuffer, StringBuilder)
- 软件开发生命周期模型 瀑布模型、增量模型、原型模型、螺旋模型、喷泉模型总结
- 欢迎使用CSDN-markdown编辑器