Skip to content

Commit 373ee31

Browse files
committed
feat: add solutions to lc problem: No.0416
No.0416.Partition Equal Subset Sum
1 parent 0139ac5 commit 373ee31

File tree

8 files changed

+408
-297
lines changed

8 files changed

+408
-297
lines changed

solution/0400-0499/0416.Partition Equal Subset Sum/README.md

Lines changed: 178 additions & 127 deletions
Large diffs are not rendered by default.

solution/0400-0499/0416.Partition Equal Subset Sum/README_EN.md

Lines changed: 165 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -33,112 +33,86 @@
3333

3434
## Solutions
3535

36-
Dynamic programming. It is similar to the 0-1 Knapsack problem.
37-
3836
<!-- tabs:start -->
3937

4038
### **Python3**
4139

4240
```python
4341
class Solution:
4442
def canPartition(self, nums: List[int]) -> bool:
45-
s = sum(nums)
46-
if s % 2 != 0:
47-
return False
48-
m, n = len(nums), s >> 1
49-
dp = [[False] * (n + 1) for _ in range(m + 1)]
50-
dp[0][0] = True
51-
for i in range(1, m + 1):
52-
for j in range(n + 1):
53-
dp[i][j] = dp[i - 1][j]
54-
if not dp[i][j] and nums[i - 1] <= j:
55-
dp[i][j] = dp[i - 1][j - nums[i - 1]]
56-
return dp[-1][-1]
57-
```
58-
59-
```python
60-
class Solution:
61-
def canPartition(self, nums: List[int]) -> bool:
62-
s = sum(nums)
63-
if s % 2 != 0:
43+
m, mod = divmod(sum(nums), 2)
44+
if mod:
6445
return False
65-
n = s >> 1
66-
dp = [False] * (n + 1)
67-
dp[0] = True
68-
for v in nums:
69-
for j in range(n, v - 1, -1):
70-
dp[j] = dp[j] or dp[j - v]
71-
return dp[-1]
46+
n = len(nums)
47+
f = [[False] * (m + 1) for _ in range(n + 1)]
48+
f[0][0] = True
49+
for i, x in enumerate(nums, 1):
50+
for j in range(m + 1):
51+
f[i][j] = f[i - 1][j] or (j >= x and f[i - 1][j - x])
52+
return f[n][m]
7253
```
7354

7455
```python
7556
class Solution:
7657
def canPartition(self, nums: List[int]) -> bool:
77-
s = sum(nums)
78-
if s % 2 != 0:
58+
m, mod = divmod(sum(nums), 2)
59+
if mod:
7960
return False
80-
target = s >> 1
81-
82-
@cache
83-
def dfs(i, s):
84-
nonlocal target
85-
if s > target or i >= len(nums):
86-
return False
87-
if s == target:
88-
return True
89-
return dfs(i + 1, s) or dfs(i + 1, s + nums[i])
90-
91-
return dfs(0, 0)
61+
f = [True] + [False] * m
62+
for x in nums:
63+
for j in range(m, x - 1, -1):
64+
f[j] = f[j] or f[j - x]
65+
return f[m]
9266
```
9367

9468
### **Java**
9569

9670
```java
9771
class Solution {
9872
public boolean canPartition(int[] nums) {
73+
// int s = Arrays.stream(nums).sum();
9974
int s = 0;
100-
for (int v : nums) {
101-
s += v;
75+
for (int x : nums) {
76+
s += x;
10277
}
103-
if (s % 2 != 0) {
78+
if (s % 2 == 1) {
10479
return false;
10580
}
106-
int m = nums.length;
107-
int n = s >> 1;
108-
boolean[][] dp = new boolean[m + 1][n + 1];
109-
dp[0][0] = true;
110-
for (int i = 1; i <= m; ++i) {
111-
for (int j = 0; j <= n; ++j) {
112-
dp[i][j] = dp[i - 1][j];
113-
if (!dp[i][j] && nums[i - 1] <= j) {
114-
dp[i][j] = dp[i - 1][j - nums[i - 1]];
115-
}
81+
int n = nums.length;
82+
int m = s >> 1;
83+
boolean[][] f = new boolean[n + 1][m + 1];
84+
f[0][0] = true;
85+
for (int i = 1; i <= n; ++i) {
86+
int x = nums[i - 1];
87+
for (int j = 0; j <= m; ++j) {
88+
f[i][j] = f[i - 1][j] || (j >= x && f[i - 1][j - x]);
11689
}
11790
}
118-
return dp[m][n];
91+
return f[n][m];
11992
}
12093
}
12194
```
12295

12396
```java
12497
class Solution {
12598
public boolean canPartition(int[] nums) {
99+
// int s = Arrays.stream(nums).sum();
126100
int s = 0;
127-
for (int v : nums) {
128-
s += v;
101+
for (int x : nums) {
102+
s += x;
129103
}
130-
if (s % 2 != 0) {
104+
if (s % 2 == 1) {
131105
return false;
132106
}
133-
int n = s >> 1;
134-
boolean[] dp = new boolean[n + 1];
135-
dp[0] = true;
136-
for (int v : nums) {
137-
for (int j = n; j >= v; --j) {
138-
dp[j] = dp[j] || dp[j - v];
107+
int m = s >> 1;
108+
boolean[] f = new boolean[m + 1];
109+
f[0] = true;
110+
for (int x : nums) {
111+
for (int j = m; j >= x; --j) {
112+
f[j] |= f[j - x];
139113
}
140114
}
141-
return dp[n];
115+
return f[m];
142116
}
143117
}
144118
```
@@ -150,17 +124,21 @@ class Solution {
150124
public:
151125
bool canPartition(vector<int>& nums) {
152126
int s = accumulate(nums.begin(), nums.end(), 0);
153-
if (s % 2 != 0) return false;
154-
int m = nums.size(), n = s >> 1;
155-
vector<vector<bool>> dp(m + 1, vector<bool>(n + 1));
156-
dp[0][0] = true;
157-
for (int i = 1; i <= m; ++i) {
158-
for (int j = 0; j <= n; ++j) {
159-
dp[i][j] = dp[i - 1][j];
160-
if (!dp[i][j] && nums[i - 1] <= j) dp[i][j] = dp[i - 1][j - nums[i - 1]];
127+
if (s % 2 == 1) {
128+
return false;
129+
}
130+
int n = nums.size();
131+
int m = s >> 1;
132+
bool f[n + 1][m + 1];
133+
memset(f, false, sizeof(f));
134+
f[0][0] = true;
135+
for (int i = 1; i <= n; ++i) {
136+
int x = nums[i - 1];
137+
for (int j = 0; j <= m; ++j) {
138+
f[i][j] = f[i - 1][j] || (j >= x && f[i - 1][j - x]);
161139
}
162140
}
163-
return dp[m][n];
141+
return f[n][m];
164142
}
165143
};
166144
```
@@ -170,14 +148,19 @@ class Solution {
170148
public:
171149
bool canPartition(vector<int>& nums) {
172150
int s = accumulate(nums.begin(), nums.end(), 0);
173-
if (s % 2 != 0) return false;
174-
int n = s >> 1;
175-
vector<bool> dp(n + 1);
176-
dp[0] = true;
177-
for (int& v : nums)
178-
for (int j = n; j >= v; --j)
179-
dp[j] = dp[j] || dp[j - v];
180-
return dp[n];
151+
if (s % 2 == 1) {
152+
return false;
153+
}
154+
int m = s >> 1;
155+
bool f[m + 1];
156+
memset(f, false, sizeof(f));
157+
f[0] = true;
158+
for (int& x : nums) {
159+
for (int j = m; j >= x; --j) {
160+
f[j] |= f[j - x];
161+
}
162+
}
163+
return f[m];
181164
}
182165
};
183166
```
@@ -187,48 +170,88 @@ public:
187170
```go
188171
func canPartition(nums []int) bool {
189172
s := 0
190-
for _, v := range nums {
191-
s += v
173+
for _, x := range nums {
174+
s += x
192175
}
193-
if s%2 != 0 {
176+
if s%2 == 1 {
194177
return false
195178
}
196-
m, n := len(nums), s>>1
197-
dp := make([][]bool, m+1)
198-
for i := range dp {
199-
dp[i] = make([]bool, n+1)
179+
n, m := len(nums), s>>1
180+
f := make([][]bool, n+1)
181+
for i := range f {
182+
f[i] = make([]bool, m+1)
200183
}
201-
dp[0][0] = true
202-
for i := 1; i <= m; i++ {
203-
for j := 0; j < n; j++ {
204-
dp[i][j] = dp[i-1][j]
205-
if !dp[i][j] && nums[i-1] <= j {
206-
dp[i][j] = dp[i-1][j-nums[i-1]]
207-
}
184+
f[0][0] = true
185+
for i := 1; i <= n; i++ {
186+
x := nums[i-1]
187+
for j := 0; j <= m; j++ {
188+
f[i][j] = f[i-1][j] || (j >= x && f[i-1][j-x])
208189
}
209190
}
210-
return dp[m][n]
191+
return f[n][m]
211192
}
212193
```
213194

214195
```go
215196
func canPartition(nums []int) bool {
216197
s := 0
217-
for _, v := range nums {
218-
s += v
198+
for _, x := range nums {
199+
s += x
219200
}
220-
if s%2 != 0 {
201+
if s%2 == 1 {
221202
return false
222203
}
223-
n := s >> 1
224-
dp := make([]bool, n+1)
225-
dp[0] = true
226-
for _, v := range nums {
227-
for j := n; j >= v; j-- {
228-
dp[j] = dp[j] || dp[j-v]
204+
m := s >> 1
205+
f := make([]bool, m+1)
206+
f[0] = true
207+
for _, x := range nums {
208+
for j := m; j >= x; j-- {
209+
f[j] = f[j] || f[j-x]
229210
}
230211
}
231-
return dp[n]
212+
return f[m]
213+
}
214+
```
215+
216+
### **TypeScript**
217+
218+
```ts
219+
function canPartition(nums: number[]): boolean {
220+
const s = nums.reduce((a, b) => a + b, 0);
221+
if (s % 2 === 1) {
222+
return false;
223+
}
224+
const n = nums.length;
225+
const m = s >> 1;
226+
const f: boolean[][] = Array(n + 1)
227+
.fill(0)
228+
.map(() => Array(m + 1).fill(false));
229+
f[0][0] = true;
230+
for (let i = 1; i <= n; ++i) {
231+
const x = nums[i - 1];
232+
for (let j = 0; j <= m; ++j) {
233+
f[i][j] = f[i - 1][j] || (j >= x && f[i - 1][j - x]);
234+
}
235+
}
236+
return f[n][m];
237+
}
238+
```
239+
240+
```ts
241+
function canPartition(nums: number[]): boolean {
242+
const s = nums.reduce((a, b) => a + b, 0);
243+
if (s % 2 === 1) {
244+
return false;
245+
}
246+
const m = s >> 1;
247+
const f: boolean[] = Array(m + 1).fill(false);
248+
f[0] = true;
249+
for (const x of nums) {
250+
for (let j = m; j >= x; --j) {
251+
f[j] = f[j] || f[j - x];
252+
}
253+
}
254+
return f[m];
232255
}
233256
```
234257

@@ -240,23 +263,45 @@ func canPartition(nums []int) bool {
240263
* @return {boolean}
241264
*/
242265
var canPartition = function (nums) {
243-
let s = 0;
244-
for (let v of nums) {
245-
s += v;
266+
const s = nums.reduce((a, b) => a + b, 0);
267+
if (s % 2 === 1) {
268+
return false;
269+
}
270+
const n = nums.length;
271+
const m = s >> 1;
272+
const f = Array(n + 1)
273+
.fill(0)
274+
.map(() => Array(m + 1).fill(false));
275+
f[0][0] = true;
276+
for (let i = 1; i <= n; ++i) {
277+
const x = nums[i - 1];
278+
for (let j = 0; j <= m; ++j) {
279+
f[i][j] = f[i - 1][j] || (j >= x && f[i - 1][j - x]);
280+
}
246281
}
247-
if (s % 2 != 0) {
282+
return f[n][m];
283+
};
284+
```
285+
286+
```js
287+
/**
288+
* @param {number[]} nums
289+
* @return {boolean}
290+
*/
291+
var canPartition = function (nums) {
292+
const s = nums.reduce((a, b) => a + b, 0);
293+
if (s % 2 === 1) {
248294
return false;
249295
}
250-
const m = nums.length;
251-
const n = s >> 1;
252-
const dp = new Array(n + 1).fill(false);
253-
dp[0] = true;
254-
for (let i = 1; i <= m; ++i) {
255-
for (let j = n; j >= nums[i - 1]; --j) {
256-
dp[j] = dp[j] || dp[j - nums[i - 1]];
296+
const m = s >> 1;
297+
const f = Array(m + 1).fill(false);
298+
f[0] = true;
299+
for (const x of nums) {
300+
for (let j = m; j >= x; --j) {
301+
f[j] = f[j] || f[j - x];
257302
}
258303
}
259-
return dp[n];
304+
return f[m];
260305
};
261306
```
262307

0 commit comments

Comments
 (0)