题目链接:https://leetcode-cn.com/problems/target-sum/
思路
1 动态规划二维数组
(1)首先求整个数组的和取值范围sum
(2)建立二维数组,数组大小为nums.size() * sum
。dp[i][j]表示为到下标i
为止和为j
的方法数,由于负数等于正数取反,如果j是负数,其方法与j是相反数时相同,即dp[i][-j]
;
(3)动态规划方程:
dp[i][j] = dp[i-1][abs(j-nums[i])] + dp[i-1][j+nums[i]]
(4)最终返回dp[nums.size()-1][abs(S)]
复杂度分析
时间复杂度:O(mn)
空间复杂度:O(mn)
m为数组长度;n为数组的和
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int S) {
auto sum = accumulate(nums.begin(), nums.end(), 0); // 和表示范围 [-sum, sum]
if(nums.empty() || S > 1000 || abs(S) > sum) // 超出表示范围
return 0;
vector<vector<int>> dp(nums.size(),vector<int>(sum+1,0));
//dp[i][j]表示为到下标i为止和为j的方法数,由于负数等于正数取反,如果j是负数,其方法与j是相反数时相同,即dp[i][-j];
dp[0][nums[0]] = (nums[0] == 0) ? 2 : 1; // 取第一个数的方法数;nums[0]==0时正负号都可加
for(int i = 1 ; i < nums.size();++i){
for(int j = 0 ; j <= sum; ++j){
int count1 = abs(j-nums[i]) > sum ? 0 : dp[i-1][abs(j-nums[i])]; // +号
int count2 = ( j + nums[i] ) > sum ? 0 : dp[i-1][j+nums[i]]; // -号
dp[i][j] = count1 + count2;
}
}
return dp[nums.size()-1][abs(S)];
}
};