加/减数组中的值得到指定的和 Target Sum
为什么80%的码农都做不了架构师?>>>
问题:
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:
解决:
① dfs。时间复杂度O(2^n)。
class Solution { //706ms
int count = 0;
public int findTargetSumWays(int[] nums, int S) {
if (nums == null || nums.length == 0) return 0;
dfs(nums,S,0,0);
return count;
}
public void dfs(int[] nums,int s,int i,int sum){
if (i == nums.length){
if (s == sum){
count ++;
}
return;
}
dfs(nums,s,i + 1,sum + nums[i]);
dfs(nums,s,i + 1,sum - nums[i]);
}
}
② 递归解决方案非常慢,因为它的运行时间是指数的。
原问题等价于:找到一个正数的子集,其余为负数,其总和为target。
设P为正数子集,N为负数子集。例如:
给定nums = [1,2,3,4,5]和target = 3,那么一个可能的解决方案是+ 1 - 2 + 3 - 4 + 5 = 3。
此时正子集是P = [1,3,5],负子集是N = [2,4]。
下面将其转换为子集总和问题:
sum(P) - sum(N) = target sum(P) + sum(N) + sum(P) - sum(N) = target + sum(P) + sum(N)2 * sum(P) = target + sum(nums)所以原来的问题已被转换为子集和问题如下:
找出nums的一个子集P,使得sum(P)=(target + sum(nums))/ 2
class Solution { //17ms
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);
}
public int subsetSum(int[] nums,int S){
int[] dp = new int[S + 1];
dp[0] = 1;//初始记录0的位置为1
for (int i = 0;i < nums.length;i ++){
for (int j = S;j >= nums[i];j --){
dp[j] += dp[j - nums[i]];
}
}
return dp[S];
}
}
转载于:https://my.oschina.net/liyurong/blog/1603737
总结
以上是生活随笔为你收集整理的加/减数组中的值得到指定的和 Target Sum的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: ajax、offset
- 下一篇: qt中设置窗口左上角的图标