トピックへのリンク: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)];
}
};