Skip to content

Commit 5a0f5b2

Browse files
committed
feat: add solutions to lcof2 problem: No.101
lcof2 No.101.Partition Equal Subset Sum
1 parent 7b3594a commit 5a0f5b2

File tree

7 files changed

+262
-1
lines changed

7 files changed

+262
-1
lines changed

lcof2/剑指 Offer II 101. 分割等和子串/README.md

Lines changed: 138 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,27 +38,164 @@
3838

3939
<p><meta charset="UTF-8" />注意:本题与主站 416&nbsp;题相同:&nbsp;<a href="https://leetcode-cn.com/problems/partition-equal-subset-sum/">https://leetcode-cn.com/problems/partition-equal-subset-sum/</a></p>
4040

41-
4241
## 解法
4342

4443
<!-- 这里可写通用的实现逻辑 -->
4544

45+
题目可以转换为 `0-1` 背包问题,在 m 个数字中选出一些数字(每个数字只能使用一次),这些数字之和恰好等于 `s / 2`(s 表示所有数字之和)。
46+
47+
也可以用 DFS + 记忆化搜索。
48+
4649
<!-- tabs:start -->
4750

4851
### **Python3**
4952

5053
<!-- 这里可写当前语言的特殊实现逻辑 -->
5154

5255
```python
56+
class Solution:
57+
def canPartition(self, nums: List[int]) -> bool:
58+
s = sum(nums)
59+
if s % 2 != 0:
60+
return False
61+
62+
m, n = len(nums), (s >> 1) + 1
63+
dp = [[False] * n for _ in range(m)]
64+
for i in range(m):
65+
dp[i][0] = True
66+
if nums[0] < n:
67+
dp[0][nums[0]] = True
68+
69+
for i in range(1, m):
70+
for j in range(n):
71+
dp[i][j] = dp[i - 1][j]
72+
if not dp[i][j] and nums[i] <= j:
73+
dp[i][j] = dp[i - 1][j - nums[i]]
74+
return dp[-1][-1]
75+
```
5376

77+
空间优化:
78+
79+
```python
80+
class Solution:
81+
def canPartition(self, nums: List[int]) -> bool:
82+
s = sum(nums)
83+
if s % 2 != 0:
84+
return False
85+
86+
m, n = len(nums), (s >> 1) + 1
87+
dp = [False] * n
88+
dp[0] = True
89+
if nums[0] < n:
90+
dp[nums[0]] = True
91+
92+
for i in range(1, m):
93+
for j in range(n - 1, nums[i] - 1, -1):
94+
dp[j] = dp[j] or dp[j - nums[i]]
95+
return dp[-1]
96+
```
97+
98+
DFS + 记忆化搜索:
99+
100+
```python
101+
class Solution:
102+
def canPartition(self, nums: List[int]) -> bool:
103+
s = sum(nums)
104+
if s % 2 != 0:
105+
return False
106+
target = s >> 1
107+
108+
@lru_cache(None)
109+
def dfs(i, s):
110+
nonlocal target
111+
if s > target or i >= len(nums):
112+
return False
113+
if s == target:
114+
return True
115+
return dfs(i + 1, s) or dfs(i + 1, s + nums[i])
116+
117+
return dfs(0, 0)
54118
```
55119

56120
### **Java**
57121

58122
<!-- 这里可写当前语言的特殊实现逻辑 -->
59123

60124
```java
125+
class Solution {
126+
public boolean canPartition(int[] nums) {
127+
int s = 0;
128+
for (int x : nums) {
129+
s += x;
130+
}
131+
if (s % 2 != 0) {
132+
return false;
133+
}
134+
int m = nums.length, n = (s >> 1) + 1;
135+
boolean[] dp = new boolean[n];
136+
dp[0] = true;
137+
if (nums[0] < n) {
138+
dp[nums[0]] = true;
139+
}
140+
for (int i = 1; i < m; ++i) {
141+
for (int j = n - 1; j >= nums[i]; --j) {
142+
dp[j] = dp[j] || dp[j - nums[i]];
143+
}
144+
}
145+
return dp[n - 1];
146+
}
147+
}
148+
```
149+
150+
### **C++**
151+
152+
```cpp
153+
class Solution {
154+
public:
155+
bool canPartition(vector<int>& nums) {
156+
int s = 0;
157+
for (int x : nums) s += x;
158+
if (s % 2 != 0) return false;
159+
int m = nums.size(), n = (s >> 1) + 1;
160+
vector<bool> dp(n);
161+
dp[0] = true;
162+
if (nums[0] < n) dp[nums[0]] = true;
163+
for (int i = 1; i < m; ++i)
164+
{
165+
for (int j = n - 1; j >= nums[i]; --j)
166+
{
167+
dp[j] = dp[j] || dp[j - nums[i]];
168+
}
169+
}
170+
return dp[n - 1];
171+
}
172+
};
173+
```
61174
175+
### **Go**
176+
177+
```go
178+
func canPartition(nums []int) bool {
179+
s := 0
180+
for _, x := range nums {
181+
s += x
182+
}
183+
if s%2 != 0 {
184+
return false
185+
}
186+
m, n := len(nums), (s>>1)+1
187+
dp := make([]bool, n)
188+
dp[0] = true
189+
if nums[0] < n {
190+
dp[nums[0]] = true
191+
}
192+
for i := 1; i < m; i++ {
193+
for j := n - 1; j >= nums[i]; j-- {
194+
dp[j] = dp[j] || dp[j-nums[i]]
195+
}
196+
}
197+
return dp[n-1]
198+
}
62199
```
63200

64201
### **...**
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
class Solution {
2+
public:
3+
bool canPartition(vector<int>& nums) {
4+
int s = 0;
5+
for (int x : nums) s += x;
6+
if (s % 2 != 0) return false;
7+
int m = nums.size(), n = (s >> 1) + 1;
8+
vector<bool> dp(n);
9+
dp[0] = true;
10+
if (nums[0] < n) dp[nums[0]] = true;
11+
for (int i = 1; i < m; ++i)
12+
{
13+
for (int j = n - 1; j >= nums[i]; --j)
14+
{
15+
dp[j] = dp[j] || dp[j - nums[i]];
16+
}
17+
}
18+
return dp[n - 1];
19+
}
20+
};
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
func canPartition(nums []int) bool {
2+
s := 0
3+
for _, x := range nums {
4+
s += x
5+
}
6+
if s%2 != 0 {
7+
return false
8+
}
9+
m, n := len(nums), (s>>1)+1
10+
dp := make([]bool, n)
11+
dp[0] = true
12+
if nums[0] < n {
13+
dp[nums[0]] = true
14+
}
15+
for i := 1; i < m; i++ {
16+
for j := n - 1; j >= nums[i]; j-- {
17+
dp[j] = dp[j] || dp[j-nums[i]]
18+
}
19+
}
20+
return dp[n-1]
21+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
class Solution {
2+
public boolean canPartition(int[] nums) {
3+
int s = 0;
4+
for (int x : nums) {
5+
s += x;
6+
}
7+
if (s % 2 != 0) {
8+
return false;
9+
}
10+
int m = nums.length, n = (s >> 1) + 1;
11+
boolean[] dp = new boolean[n];
12+
dp[0] = true;
13+
if (nums[0] < n) {
14+
dp[nums[0]] = true;
15+
}
16+
for (int i = 1; i < m; ++i) {
17+
for (int j = n - 1; j >= nums[i]; --j) {
18+
dp[j] = dp[j] || dp[j - nums[i]];
19+
}
20+
}
21+
return dp[n - 1];
22+
}
23+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
class Solution:
2+
def canPartition(self, nums: List[int]) -> bool:
3+
s = sum(nums)
4+
if s % 2 != 0:
5+
return False
6+
7+
m, n = len(nums), (s >> 1) + 1
8+
dp = [False] * n
9+
dp[0] = True
10+
if nums[0] < n:
11+
dp[nums[0]] = True
12+
13+
for i in range(1, m):
14+
for j in range(n - 1, nums[i] - 1, -1):
15+
dp[j] = dp[j] or dp[j - nums[i]]
16+
return dp[-1]

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040

4141
题目可以转换为 `0-1` 背包问题,在 m 个数字中选出一些数字(每个数字只能使用一次),这些数字之和恰好等于 `s / 2`(s 表示所有数字之和)。
4242

43+
也可以用 DFS + 记忆化搜索。
44+
4345
<!-- tabs:start -->
4446

4547
### **Python3**
@@ -89,6 +91,28 @@ class Solution:
8991
return dp[-1]
9092
```
9193

94+
DFS + 记忆化搜索:
95+
96+
```python
97+
class Solution:
98+
def canPartition(self, nums: List[int]) -> bool:
99+
s = sum(nums)
100+
if s % 2 != 0:
101+
return False
102+
target = s >> 1
103+
104+
@lru_cache(None)
105+
def dfs(i, s):
106+
nonlocal target
107+
if s > target or i >= len(nums):
108+
return False
109+
if s == target:
110+
return True
111+
return dfs(i + 1, s) or dfs(i + 1, s + nums[i])
112+
113+
return dfs(0, 0)
114+
```
115+
92116
### **Java**
93117

94118
<!-- 这里可写当前语言的特殊实现逻辑 -->

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,26 @@ class Solution:
7878
return dp[-1]
7979
```
8080

81+
```python
82+
class Solution:
83+
def canPartition(self, nums: List[int]) -> bool:
84+
s = sum(nums)
85+
if s % 2 != 0:
86+
return False
87+
target = s >> 1
88+
89+
@lru_cache(None)
90+
def dfs(i, s):
91+
nonlocal target
92+
if s > target or i >= len(nums):
93+
return False
94+
if s == target:
95+
return True
96+
return dfs(i + 1, s) or dfs(i + 1, s + nums[i])
97+
98+
return dfs(0, 0)
99+
```
100+
81101
### **Java**
82102

83103
```java

0 commit comments

Comments
 (0)