53
53
54
54
<!-- 这里可写通用的实现逻辑 -->
55
55
56
- 题目可以转换为 ` 0-1 ` 背包问题,只不过下标可能会出现负数,需要特殊处理。
56
+ ** 方法一:动态规划 **
57
57
58
- 也可以用 DFS 记忆化搜索 。
58
+ 题目可以转换为 ` 0-1 ` 背包问题 。
59
59
60
- <!-- tabs:start -->
60
+ 设整数数组总和为 ` s ` ,添加 ` - ` 号的元素之和为 ` x ` ,则添加 ` + ` 号的元素之和为 ` s - x ` ,那么 ` s - x - x = target ` , ` 2x = s - target ` 。左式成立需要满足 ` s - target ` 一定大于等于 0,并且能够被 2 整除。在此前提下,我们可以将问题抽象为: 从数组中选出若干个数,使得选出的元素之和为 x。显然这是一个 ` 0-1 ` 背包问题。
61
61
62
- ### ** Python3 **
62
+ 定义 ` dp[i][j] ` 表示从前 i 个数中选出若干个数,使得所选元素之和为 j 的所有方案数。
63
63
64
- ** 0-1 背包 **
64
+ <!-- tabs:start -->
65
65
66
- ``` python
67
- class Solution :
68
- def findTargetSumWays (self , nums : List[int ], target : int ) -> int :
69
- if target < - 1000 or target > 1000 :
70
- return 0
71
- n = len (nums)
72
- dp = [[0 ] * 2001 for i in range (n)]
73
- dp[0 ][nums[0 ] + 1000 ] += 1
74
- dp[0 ][- nums[0 ] + 1000 ] += 1
75
- for i in range (1 , n):
76
- for j in range (- 1000 , 1001 ):
77
- if dp[i - 1 ][j + 1000 ] > 0 :
78
- dp[i][j + nums[i] + 1000 ] += dp[i - 1 ][j + 1000 ]
79
- dp[i][j - nums[i] + 1000 ] += dp[i - 1 ][j + 1000 ]
80
- return dp[n - 1 ][target + 1000 ]
81
- ```
66
+ ### ** Python3**
82
67
83
- 设:添加 ` - ` 号的元素之和为 ` x ` ,则添加 ` + ` 号的元素之和为 ` s - x ` , ` s - x - x = target ` , ` 2x = s - target ` 。需要满足 ` s - target ` 一定大于等于 0,并且能够被 2 整除。
68
+ 动态规划—— ` 0-1 ` 背包朴素做法:
84
69
85
70
``` python
86
71
class Solution :
87
72
def findTargetSumWays (self , nums : List[int ], target : int ) -> int :
88
73
s = sum (nums)
89
- if s - target < 0 or (s - target) % 2 != 0 :
74
+ if s < target or (s - target) % 2 != 0 :
90
75
return 0
91
- target = (s - target) // 2 + 1
92
- n = len (nums) + 1
93
- dp = [[0 ] * target for _ in range (n)]
76
+ m, n = len (nums) + 1 , (s - target) // 2 + 1
77
+ dp = [[0 ] * n for _ in range (m)]
94
78
dp[0 ][0 ] = 1
95
- for i in range (1 , n ):
96
- for j in range (target ):
79
+ for i in range (1 , m ):
80
+ for j in range (n ):
97
81
dp[i][j] = dp[i - 1 ][j]
98
82
if nums[i - 1 ] <= j:
99
83
dp[i][j] += dp[i - 1 ][j - nums[i - 1 ]]
100
84
return dp[- 1 ][- 1 ]
101
85
```
102
86
103
- 空间优化 :
87
+ 动态规划—— ` 0-1 ` 背包空间优化 :
104
88
105
89
``` python
106
90
class Solution :
107
91
def findTargetSumWays (self , nums : List[int ], target : int ) -> int :
108
92
s = sum (nums)
109
- if s - target < 0 or (s - target) % 2 != 0 :
93
+ if s < target or (s - target) % 2 != 0 :
110
94
return 0
111
- target = (s - target) // 2 + 1
112
- n = len (nums) + 1
113
- dp = [0 ] * target
95
+ m, n = len (nums) + 1 , (s - target) // 2 + 1
96
+ dp = [0 ] * n
114
97
dp[0 ] = 1
115
- for i in range (1 , n ):
116
- for j in range (target - 1 , nums[i - 1 ] - 1 , - 1 ):
98
+ for i in range (1 , m ):
99
+ for j in range (n - 1 , nums[i - 1 ] - 1 , - 1 ):
117
100
dp[j] += dp[j - nums[i - 1 ]]
118
101
return dp[- 1 ]
119
102
```
120
103
121
- ** DFS**
104
+ DFS:
122
105
123
106
``` python
124
107
class Solution :
@@ -142,131 +125,180 @@ class Solution:
142
125
``` java
143
126
class Solution {
144
127
public int findTargetSumWays (int [] nums , int target ) {
145
- if (target < - 1000 || target > 1000 ) {
128
+ int s = 0 ;
129
+ for (int v : nums) {
130
+ s += v;
131
+ }
132
+ if (s < target || (s - target) % 2 != 0 ) {
146
133
return 0 ;
147
134
}
148
-
149
- int n = nums. length;
150
- int [][] dp = new int [n][2001 ];
151
-
152
- dp[0 ][nums[0 ] + 1000 ] += 1 ;
153
- dp[0 ][- nums[0 ] + 1000 ] += 1 ;
154
-
155
- for (int i = 1 ; i < n; i++ ) {
156
- for (int j = - 1000 ; j <= 1000 ; j++ ) {
157
- if (dp[i - 1 ][j + 1000 ] > 0 ) {
158
- dp[i][j + nums[i] + 1000 ] += dp[i - 1 ][j + 1000 ];
159
- dp[i][j - nums[i] + 1000 ] += dp[i - 1 ][j + 1000 ];
135
+ int m = nums. length;
136
+ int n = (s - target) / 2 ;
137
+ int [][] dp = new int [m + 1 ][n + 1 ];
138
+ dp[0 ][0 ] = 1 ;
139
+ for (int i = 1 ; i <= m; ++ i) {
140
+ for (int j = 0 ; j <= n; ++ j) {
141
+ dp[i][j] = dp[i - 1 ][j];
142
+ if (nums[i - 1 ] <= j) {
143
+ dp[i][j] += dp[i - 1 ][j - nums[i - 1 ]];
160
144
}
161
145
}
162
146
}
163
- return dp[n - 1 ][target + 1000 ];
147
+ return dp[m][n ];
164
148
}
165
149
}
166
150
```
167
151
168
- 空间优化:
169
-
170
152
``` java
171
153
class Solution {
172
154
public int findTargetSumWays (int [] nums , int target ) {
173
155
int s = 0 ;
174
- for (int x : nums) {
175
- s += x ;
156
+ for (int v : nums) {
157
+ s += v ;
176
158
}
177
- if (s - target < 0 || (s - target) % 2 != 0 ) {
159
+ if (s < target || (s - target) % 2 != 0 ) {
178
160
return 0 ;
179
161
}
180
- target = (s - target) / 2 + 1 ;
181
- int [] dp = new int [target];
162
+ int m = nums. length;
163
+ int n = (s - target) / 2 ;
164
+ int [] dp = new int [n + 1 ];
182
165
dp[0 ] = 1 ;
183
- for (int i = 1 ; i < nums . length + 1 ; ++ i) {
184
- for (int j = target - 1 ; j >= nums[i - 1 ]; -- j) {
166
+ for (int i = 1 ; i <= m ; ++ i) {
167
+ for (int j = n ; j >= nums[i - 1 ]; -- j) {
185
168
dp[j] += dp[j - nums[i - 1 ]];
186
169
}
187
170
}
188
- return dp[target - 1 ];
171
+ return dp[n ];
189
172
}
190
173
}
191
174
```
192
175
193
176
### ** C++**
194
177
195
- 空间优化:
178
+ ``` cpp
179
+ class Solution {
180
+ public:
181
+ int findTargetSumWays(vector<int >& nums, int target) {
182
+ int s = 0;
183
+ for (int& v : nums) s += v;
184
+ if (s < target || (s - target) % 2 != 0) return 0;
185
+ int m = nums.size(), n = (s - target) / 2;
186
+ vector<vector<int >> dp(m + 1, vector<int >(n + 1));
187
+ dp[ 0] [ 0 ] = 1;
188
+ for (int i = 1; i <= m; ++i)
189
+ {
190
+ for (int j = 0; j <= n; ++j)
191
+ {
192
+ dp[ i] [ j ] += dp[ i - 1] [ j ] ;
193
+ if (nums[ i - 1] <= j) dp[ i] [ j ] += dp[ i - 1] [ j - nums[ i - 1]] ;
194
+ }
195
+ }
196
+ return dp[ m] [ n ] ;
197
+ }
198
+ };
199
+ ```
196
200
197
201
```cpp
198
202
class Solution {
199
203
public:
200
204
int findTargetSumWays(vector<int>& nums, int target) {
201
205
int s = 0;
202
- for (int x : nums) s += x ;
203
- if (s - target < 0 || (s - target) % 2 != 0) return 0;
204
- target = ( s - target) / 2 + 1 ;
205
- vector<int > dp(target );
206
+ for (int& v : nums) s += v ;
207
+ if (s < target || (s - target) % 2 != 0) return 0;
208
+ int m = nums.size(), n = ( s - target) / 2;
209
+ vector<int> dp(n + 1 );
206
210
dp[0] = 1;
207
- for (int i = 1; i < nums.size() + 1 ; ++i)
211
+ for (int i = 1; i <= m ; ++i)
208
212
{
209
- for (int j = target - 1 ; j >= nums[ i - 1] ; --j)
213
+ for (int j = n ; j >= nums[i - 1]; --j)
210
214
{
211
215
dp[j] += dp[j - nums[i - 1]];
212
216
}
213
217
}
214
- return dp[ target - 1 ] ;
218
+ return dp[n ];
215
219
}
216
220
};
217
221
```
218
222
219
223
### ** Go**
220
224
221
- <!-- 这里可写当前语言的特殊实现逻辑 -->
222
-
223
225
``` go
224
226
func findTargetSumWays (nums []int , target int ) int {
225
- if target < -1000 || target > 1000 {
227
+ s := 0
228
+ for _ , v := range nums {
229
+ s += v
230
+ }
231
+ if s < target || (s-target)%2 != 0 {
226
232
return 0
227
233
}
228
- n := len(nums)
229
- dp := make([][]int, n )
230
- for i := 0; i < n; i++ {
231
- dp[i] = make([]int, 2001 )
234
+ m , n := len (nums), (s-target)/ 2
235
+ dp := make ([][]int , m+ 1 )
236
+ for i := range dp {
237
+ dp[i] = make ([]int , n+ 1 )
232
238
}
233
- dp[0][nums[0]+1000] += 1
234
- dp[0][-nums[0]+1000] += 1
235
- for i := 1; i < n; i++ {
236
- for j := -1000; j <= 1000; j++ {
237
- if dp[i-1][j+1000] > 0 {
238
- dp[i][j+nums[i]+1000] += dp[i-1][j+1000]
239
- dp[i][j-nums[i]+1000] += dp[i-1][j+1000]
239
+ dp[0 ][0 ] = 1
240
+ for i := 1 ; i <= m; i++ {
241
+ for j := 0 ; j <= n; j++ {
242
+ dp[i][j] = dp[i-1 ][j]
243
+ if nums[i-1 ] <= j {
244
+ dp[i][j] += dp[i-1 ][j-nums[i-1 ]]
240
245
}
241
246
}
242
247
}
243
- return dp[n-1][target+1000 ]
248
+ return dp[m][n ]
244
249
}
245
250
```
246
251
247
- 空间优化:
248
-
249
252
``` go
250
253
func findTargetSumWays (nums []int , target int ) int {
251
254
s := 0
252
- for _ , x := range nums {
253
- s += x
255
+ for _ , v := range nums {
256
+ s += v
254
257
}
255
- if s-target < 0 || (s-target)%2 != 0 {
258
+ if s < target || (s-target)%2 != 0 {
256
259
return 0
257
260
}
258
- target = ( s-target)/2 + 1
259
- dp := make ([]int , target )
261
+ m , n := len (nums), ( s-target)/2
262
+ dp := make ([]int , n+ 1 )
260
263
dp[0 ] = 1
261
- for i := 1 ; i < len (nums)+ 1 ; i++ {
262
- for j := target - 1 ; j >= nums[i-1 ]; j-- {
264
+ for i := 1 ; i <= m ; i++ {
265
+ for j := n ; j >= nums[i-1 ]; j-- {
263
266
dp[j] += dp[j-nums[i-1 ]]
264
267
}
265
268
}
266
- return dp[target- 1 ]
269
+ return dp[n ]
267
270
}
268
271
```
269
272
273
+ ### ** JavaScript**
274
+
275
+ ``` js
276
+ /**
277
+ * @param {number[]} nums
278
+ * @param {number} target
279
+ * @return {number}
280
+ */
281
+ var findTargetSumWays = function (nums , target ) {
282
+ let s = 0 ;
283
+ for (let v of nums) {
284
+ s += v;
285
+ }
286
+ if (s < target || (s - target) % 2 != 0 ) {
287
+ return 0 ;
288
+ }
289
+ const m = nums .length ;
290
+ const n = (s - target) / 2 ;
291
+ let dp = new Array (n + 1 ).fill (0 );
292
+ dp[0 ] = 1 ;
293
+ for (let i = 1 ; i <= m; ++ i) {
294
+ for (let j = n; j >= nums[i - 1 ]; -- j) {
295
+ dp[j] += dp[j - nums[i - 1 ]];
296
+ }
297
+ }
298
+ return dp[n];
299
+ };
300
+ ```
301
+
270
302
### ** ...**
271
303
272
304
```
0 commit comments