Skip to content

Commit 7db2f04

Browse files
committed
feat: add solutions to lc problem: No.0494
No.0494.Target Sum
1 parent 2e40b2f commit 7db2f04

File tree

9 files changed

+339
-241
lines changed

9 files changed

+339
-241
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
- [最长公共子序列](/solution/1100-1199/1143.Longest%20Common%20Subsequence/README.md) - 线性 DP、最长公共子序列模型
7878
- [两个字符串的最小 ASCII 删除和](/solution/0700-0799/0712.Minimum%20ASCII%20Delete%20Sum%20for%20Two%20Strings/README.md) - 线性 DP、最长公共子序列模型
7979
- [两个字符串的删除操作](/solution/0500-0599/0583.Delete%20Operation%20for%20Two%20Strings/README.md) - 线性 DP、最长公共子序列模型
80+
- [目标和](/solution/0400-0499/0494.Target%20Sum/README.md) - 0-1 背包问题
8081
<!-- 背包问题、状态机模型、状压DP、区间DP、树形DP、数位DP 待补充 -->
8182

8283
### 4. 高级数据结构

README_EN.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ Complete solutions to [LeetCode](https://leetcode.com/problemset/all/), [LCOF](h
7474
- [Longest Common Subsequence](/solution/1100-1199/1143.Longest%20Common%20Subsequence/README_EN.md) - Linear problem, LCS
7575
- [Minimum ASCII Delete Sum for Two Strings](/solution/0700-0799/0712.Minimum%20ASCII%20Delete%20Sum%20for%20Two%20Strings/README_EN.md) - Linear problem, LCS
7676
- [Delete Operation for Two Strings](/solution/0500-0599/0583.Delete%20Operation%20for%20Two%20Strings/README_EN.md) - Linear problem, LCS
77+
- [Target Sum](/solution/0400-0499/0494.Target%20Sum/README_EN.md) - 0-1 Knapsack
7778

7879
### 4. Advanced Data Structures
7980

solution/0400-0499/0494.Target Sum/README.md

Lines changed: 125 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -53,72 +53,55 @@
5353

5454
<!-- 这里可写通用的实现逻辑 -->
5555

56-
题目可以转换为 `0-1` 背包问题,只不过下标可能会出现负数,需要特殊处理。
56+
**方法一:动态规划**
5757

58-
也可以用 DFS 记忆化搜索
58+
题目可以转换为 `0-1` 背包问题
5959

60-
<!-- tabs:start -->
60+
设整数数组总和为 `s`,添加 `-` 号的元素之和为 `x`,则添加 `+` 号的元素之和为 `s - x`,那么 `s - x - x = target``2x = s - target`。左式成立需要满足 `s - target` 一定大于等于 0,并且能够被 2 整除。在此前提下,我们可以将问题抽象为: 从数组中选出若干个数,使得选出的元素之和为 x。显然这是一个 `0-1` 背包问题。
6161

62-
### **Python3**
62+
定义 `dp[i][j]` 表示从前 i 个数中选出若干个数,使得所选元素之和为 j 的所有方案数。
6363

64-
**0-1 背包**
64+
<!-- tabs:start -->
6565

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**
8267

83-
设:添加 `-` 号的元素之和为 `x`,则添加 `+` 号的元素之和为 `s - x``s - x - x = target``2x = s - target`。需要满足 `s - target` 一定大于等于 0,并且能够被 2 整除。
68+
动态规划——`0-1` 背包朴素做法:
8469

8570
```python
8671
class Solution:
8772
def findTargetSumWays(self, nums: List[int], target: int) -> int:
8873
s = sum(nums)
89-
if s - target < 0 or (s - target) % 2 != 0:
74+
if s < target or (s - target) % 2 != 0:
9075
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)]
9478
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):
9781
dp[i][j] = dp[i - 1][j]
9882
if nums[i - 1] <= j:
9983
dp[i][j] += dp[i - 1][j - nums[i - 1]]
10084
return dp[-1][-1]
10185
```
10286

103-
空间优化
87+
动态规划——`0-1` 背包空间优化
10488

10589
```python
10690
class Solution:
10791
def findTargetSumWays(self, nums: List[int], target: int) -> int:
10892
s = sum(nums)
109-
if s - target < 0 or (s - target) % 2 != 0:
93+
if s < target or (s - target) % 2 != 0:
11094
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
11497
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):
117100
dp[j] += dp[j - nums[i - 1]]
118101
return dp[-1]
119102
```
120103

121-
**DFS**
104+
DFS
122105

123106
```python
124107
class Solution:
@@ -142,131 +125,180 @@ class Solution:
142125
```java
143126
class Solution {
144127
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) {
146133
return 0;
147134
}
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]];
160144
}
161145
}
162146
}
163-
return dp[n - 1][target + 1000];
147+
return dp[m][n];
164148
}
165149
}
166150
```
167151

168-
空间优化:
169-
170152
```java
171153
class Solution {
172154
public int findTargetSumWays(int[] nums, int target) {
173155
int s = 0;
174-
for (int x : nums) {
175-
s += x;
156+
for (int v : nums) {
157+
s += v;
176158
}
177-
if (s - target < 0 || (s - target) % 2 != 0) {
159+
if (s < target || (s - target) % 2 != 0) {
178160
return 0;
179161
}
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];
182165
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) {
185168
dp[j] += dp[j - nums[i - 1]];
186169
}
187170
}
188-
return dp[target - 1];
171+
return dp[n];
189172
}
190173
}
191174
```
192175

193176
### **C++**
194177

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+
```
196200
197201
```cpp
198202
class Solution {
199203
public:
200204
int findTargetSumWays(vector<int>& nums, int target) {
201205
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);
206210
dp[0] = 1;
207-
for (int i = 1; i < nums.size() + 1; ++i)
211+
for (int i = 1; i <= m; ++i)
208212
{
209-
for (int j = target - 1; j >= nums[i - 1]; --j)
213+
for (int j = n; j >= nums[i - 1]; --j)
210214
{
211215
dp[j] += dp[j - nums[i - 1]];
212216
}
213217
}
214-
return dp[target - 1];
218+
return dp[n];
215219
}
216220
};
217221
```
218222

219223
### **Go**
220224

221-
<!-- 这里可写当前语言的特殊实现逻辑 -->
222-
223225
```go
224226
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 {
226232
return 0
227233
}
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)
232238
}
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]]
240245
}
241246
}
242247
}
243-
return dp[n-1][target+1000]
248+
return dp[m][n]
244249
}
245250
```
246251

247-
空间优化:
248-
249252
```go
250253
func findTargetSumWays(nums []int, target int) int {
251254
s := 0
252-
for _, x := range nums {
253-
s += x
255+
for _, v := range nums {
256+
s += v
254257
}
255-
if s-target < 0 || (s-target)%2 != 0 {
258+
if s < target || (s-target)%2 != 0 {
256259
return 0
257260
}
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)
260263
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-- {
263266
dp[j] += dp[j-nums[i-1]]
264267
}
265268
}
266-
return dp[target-1]
269+
return dp[n]
267270
}
268271
```
269272

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+
270302
### **...**
271303

272304
```

0 commit comments

Comments
 (0)