1.题目描述
1.1笔者分析
个人觉得这题还是很值得研究的,重点不在如何求解这题,而是一个算法思想,如何将一种类型的题目转换成另一种类型题。虽然这题可以用深度优先搜索来解,但显然是有点复杂的。下面对原问题进行分析。
原问题等同于:找到nums一个正子集和一个负子集,使得总和等于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§=(target+sum(nums))/2。题目转化为01背包,也就是能组合成容量为sum§的方式有多少种
class Solution {
public int findTargetSumWays(int[] nums, int S) {
int sum=0;
for(int num:nums){
sum+=num;
}
if(sum<S||(sum+S)%2==1){
return 0;
}
int w=(sum+S)/2;
int[] dp=new int[w+1];
dp[0]=1;
for(int num:nums){
for(int j=w;j>=num;j--){
dp[j]+=dp[j-num];
}
}
return dp[w];
}
}