classSolution { public: intfindTargetSumWays(vector<int>& nums, int target){ int s = 0, n = nums.size(); for (int i = 0; i < n; ++i) s += nums[i]; s += target; if (s < 0 || s & 1) return0; int m = s >> 1, f[21][1001]; memset(f, 0, sizeof(f)); f[0][0] = 1; for (int i = 0; i < n; ++i) { int x = nums[i]; for (int j = 0; j <= m; ++j) { f[i + 1][j] += f[i][j]; if (j + x <= m) f[i + 1][j + x] += f[i][j]; } } return f[n][m]; } };
滚掉第一维,得到代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
classSolution { public: intfindTargetSumWays(vector<int>& nums, int target){ int s = 0, n = nums.size(); for (int i = 0; i < n; ++i) s += nums[i]; s += target; if (s < 0 || s & 1) return0; int m = s >> 1, f[1001]; memset(f, 0, sizeof(f)); f[0] = 1; for (int i = 0; i < n; ++i) { int x = nums[i]; for (int j = m; j >= 0; --j) { if (j + x <= m) f[j + x] += f[j]; } } return f[m]; } };
classSolution { public: unordered_map<int, int> subset(vector<int> nums){ unordered_map<int, int> mp; int n = nums.size(); for (int i = 0; i < (1 << n); ++i) { int s = 0; for (int j = 0; j < n; ++j) { if ((1 << j) & i) s += nums[j]; } mp[s]++; } return mp; } intfindTargetSumWays(vector<int>& nums, int target){ // 先去掉不可能情况 int s = 0, n = nums.size(); for (int i = 0; i < n; ++i) s += nums[i]; s += target; if (s < 0 || s & 1) return0; s >>= 1; // 乘法原理 auto cnt1 = subset(vector<int>(nums.begin(), nums.begin() + n / 2)); auto cnt2 = subset(vector<int>(nums.begin() + n / 2, nums.end())); int ans = 0; for (auto& [x, c1] : cnt1) { ans += c1 * cnt2[s - x]; } return ans; } };