Skip to content

Commit

Permalink
feat: add solutions to lcof2 problem: No.101
Browse files Browse the repository at this point in the history
lcof2 No.101.Partition Equal Subset Sum
  • Loading branch information
yanglbme committed Dec 7, 2021
1 parent 7b3594a commit 5a0f5b2
Show file tree
Hide file tree
Showing 7 changed files with 262 additions and 1 deletion.
139 changes: 138 additions & 1 deletion lcof2/剑指 Offer II 101. 分割等和子串/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,27 +38,164 @@

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


## 解法

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

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

也可以用 DFS + 记忆化搜索。

<!-- tabs:start -->

### **Python3**

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

```python
class Solution:
def canPartition(self, nums: List[int]) -> bool:
s = sum(nums)
if s % 2 != 0:
return False

m, n = len(nums), (s >> 1) + 1
dp = [[False] * n for _ in range(m)]
for i in range(m):
dp[i][0] = True
if nums[0] < n:
dp[0][nums[0]] = True

for i in range(1, m):
for j in range(n):
dp[i][j] = dp[i - 1][j]
if not dp[i][j] and nums[i] <= j:
dp[i][j] = dp[i - 1][j - nums[i]]
return dp[-1][-1]
```

空间优化:

```python
class Solution:
def canPartition(self, nums: List[int]) -> bool:
s = sum(nums)
if s % 2 != 0:
return False

m, n = len(nums), (s >> 1) + 1
dp = [False] * n
dp[0] = True
if nums[0] < n:
dp[nums[0]] = True

for i in range(1, m):
for j in range(n - 1, nums[i] - 1, -1):
dp[j] = dp[j] or dp[j - nums[i]]
return dp[-1]
```

DFS + 记忆化搜索:

```python
class Solution:
def canPartition(self, nums: List[int]) -> bool:
s = sum(nums)
if s % 2 != 0:
return False
target = s >> 1

@lru_cache(None)
def dfs(i, s):
nonlocal target
if s > target or i >= len(nums):
return False
if s == target:
return True
return dfs(i + 1, s) or dfs(i + 1, s + nums[i])

return dfs(0, 0)
```

### **Java**

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

```java
class Solution {
public boolean canPartition(int[] nums) {
int s = 0;
for (int x : nums) {
s += x;
}
if (s % 2 != 0) {
return false;
}
int m = nums.length, n = (s >> 1) + 1;
boolean[] dp = new boolean[n];
dp[0] = true;
if (nums[0] < n) {
dp[nums[0]] = true;
}
for (int i = 1; i < m; ++i) {
for (int j = n - 1; j >= nums[i]; --j) {
dp[j] = dp[j] || dp[j - nums[i]];
}
}
return dp[n - 1];
}
}
```

### **C++**

```cpp
class Solution {
public:
bool canPartition(vector<int>& nums) {
int s = 0;
for (int x : nums) s += x;
if (s % 2 != 0) return false;
int m = nums.size(), n = (s >> 1) + 1;
vector<bool> dp(n);
dp[0] = true;
if (nums[0] < n) dp[nums[0]] = true;
for (int i = 1; i < m; ++i)
{
for (int j = n - 1; j >= nums[i]; --j)
{
dp[j] = dp[j] || dp[j - nums[i]];
}
}
return dp[n - 1];
}
};
```
### **Go**
```go
func canPartition(nums []int) bool {
s := 0
for _, x := range nums {
s += x
}
if s%2 != 0 {
return false
}
m, n := len(nums), (s>>1)+1
dp := make([]bool, n)
dp[0] = true
if nums[0] < n {
dp[nums[0]] = true
}
for i := 1; i < m; i++ {
for j := n - 1; j >= nums[i]; j-- {
dp[j] = dp[j] || dp[j-nums[i]]
}
}
return dp[n-1]
}
```

### **...**
Expand Down
20 changes: 20 additions & 0 deletions lcof2/剑指 Offer II 101. 分割等和子串/Solution.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
class Solution {
public:
bool canPartition(vector<int>& nums) {
int s = 0;
for (int x : nums) s += x;
if (s % 2 != 0) return false;
int m = nums.size(), n = (s >> 1) + 1;
vector<bool> dp(n);
dp[0] = true;
if (nums[0] < n) dp[nums[0]] = true;
for (int i = 1; i < m; ++i)
{
for (int j = n - 1; j >= nums[i]; --j)
{
dp[j] = dp[j] || dp[j - nums[i]];
}
}
return dp[n - 1];
}
};
21 changes: 21 additions & 0 deletions lcof2/剑指 Offer II 101. 分割等和子串/Solution.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
func canPartition(nums []int) bool {
s := 0
for _, x := range nums {
s += x
}
if s%2 != 0 {
return false
}
m, n := len(nums), (s>>1)+1
dp := make([]bool, n)
dp[0] = true
if nums[0] < n {
dp[nums[0]] = true
}
for i := 1; i < m; i++ {
for j := n - 1; j >= nums[i]; j-- {
dp[j] = dp[j] || dp[j-nums[i]]
}
}
return dp[n-1]
}
23 changes: 23 additions & 0 deletions lcof2/剑指 Offer II 101. 分割等和子串/Solution.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
class Solution {
public boolean canPartition(int[] nums) {
int s = 0;
for (int x : nums) {
s += x;
}
if (s % 2 != 0) {
return false;
}
int m = nums.length, n = (s >> 1) + 1;
boolean[] dp = new boolean[n];
dp[0] = true;
if (nums[0] < n) {
dp[nums[0]] = true;
}
for (int i = 1; i < m; ++i) {
for (int j = n - 1; j >= nums[i]; --j) {
dp[j] = dp[j] || dp[j - nums[i]];
}
}
return dp[n - 1];
}
}
16 changes: 16 additions & 0 deletions lcof2/剑指 Offer II 101. 分割等和子串/Solution.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
class Solution:
def canPartition(self, nums: List[int]) -> bool:
s = sum(nums)
if s % 2 != 0:
return False

m, n = len(nums), (s >> 1) + 1
dp = [False] * n
dp[0] = True
if nums[0] < n:
dp[nums[0]] = True

for i in range(1, m):
for j in range(n - 1, nums[i] - 1, -1):
dp[j] = dp[j] or dp[j - nums[i]]
return dp[-1]
24 changes: 24 additions & 0 deletions solution/0400-0499/0416.Partition Equal Subset Sum/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@

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

也可以用 DFS + 记忆化搜索。

<!-- tabs:start -->

### **Python3**
Expand Down Expand Up @@ -89,6 +91,28 @@ class Solution:
return dp[-1]
```

DFS + 记忆化搜索:

```python
class Solution:
def canPartition(self, nums: List[int]) -> bool:
s = sum(nums)
if s % 2 != 0:
return False
target = s >> 1

@lru_cache(None)
def dfs(i, s):
nonlocal target
if s > target or i >= len(nums):
return False
if s == target:
return True
return dfs(i + 1, s) or dfs(i + 1, s + nums[i])

return dfs(0, 0)
```

### **Java**

<!-- 这里可写当前语言的特殊实现逻辑 -->
Expand Down
20 changes: 20 additions & 0 deletions solution/0400-0499/0416.Partition Equal Subset Sum/README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,26 @@ class Solution:
return dp[-1]
```

```python
class Solution:
def canPartition(self, nums: List[int]) -> bool:
s = sum(nums)
if s % 2 != 0:
return False
target = s >> 1

@lru_cache(None)
def dfs(i, s):
nonlocal target
if s > target or i >= len(nums):
return False
if s == target:
return True
return dfs(i + 1, s) or dfs(i + 1, s + nums[i])

return dfs(0, 0)
```

### **Java**

```java
Expand Down

0 comments on commit 5a0f5b2

Please sign in to comment.