Skip to content

Commit f325b4c

Browse files
committed
feat: add solutions to lc problem: No.2025
No.2025.Maximum Number of Ways to Partition an Array
1 parent 56f596f commit f325b4c

File tree

6 files changed

+342
-2
lines changed

6 files changed

+342
-2
lines changed

solution/2000-2099/2025.Maximum Number of Ways to Partition an Array/README.md

Lines changed: 125 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,22 +60,146 @@
6060

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

63+
**方法一:前缀和 + 哈希表**
64+
65+
我们可以先预处理得到数组 $nums$ 对应的前缀和数组 $s$,其中 $s[i]$ 表示数组 $nums[0,...i-1]$ 的和。那么数组所有元素之和为 $s[n - 1]$。
66+
67+
如果不修改数组 $nums$,那么两个子数组的和相等的条件是 $s[n - 1]$ 必须为偶数,如果 $s[n - 1]$ 为偶数,那么我们求出 $ans = \frac{right[s[n - 1] / 2]}{2}$。
68+
69+
如果修改数组 $nums$,那么我们可以枚举每一个修改的位置 $i$,将 $nums[i]$ 修改为 $k$,那么数组总和的变化量 $d = k - nums[i]$,此时 $i$ 左侧部分的和保持不变,那么合法的分割要满足 $s[i] = s[n - 1] + d - s[i]$,即 $s[i] = \frac{s[n - 1] + d}{2}$;而右侧部分的每个前缀和都增加了 $d$,那么合法的分割要满足 $s[i] + d = s[n - 1] + d - (s[i] + d)$,即 $s[i] = \frac{s[n - 1] - d}{2}$。我们用哈希表 $left$ 和 $right$ 分别记录左侧部分和右侧部分每个前缀和出现的次数,那么我们可以求出 $ans = max(ans, left[\frac{s[n - 1] + d}{2}]) + right[\frac{s[n - 1] - d}{2}]$。
70+
71+
最后,我们返回 $ans$ 即可。
72+
73+
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $nums$ 的长度。
74+
6375
<!-- tabs:start -->
6476

6577
### **Python3**
6678

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

6981
```python
70-
82+
class Solution:
83+
def waysToPartition(self, nums: List[int], k: int) -> int:
84+
n = len(nums)
85+
s = [nums[0]] * n
86+
right = defaultdict(int)
87+
for i in range(1, n):
88+
s[i] = s[i - 1] + nums[i]
89+
right[s[i - 1]] += 1
90+
91+
ans = 0
92+
if s[-1] % 2 == 0:
93+
ans = right[s[-1] // 2]
94+
95+
left = defaultdict(int)
96+
for v, x in zip(s, nums):
97+
d = k - x
98+
if (s[-1] + d) % 2 == 0:
99+
t = left[(s[-1] + d) // 2] + right[(s[-1] - d) // 2]
100+
if ans < t:
101+
ans = t
102+
left[v] += 1
103+
right[v] -= 1
104+
return ans
71105
```
72106

73107
### **Java**
74108

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

77111
```java
112+
class Solution {
113+
public int waysToPartition(int[] nums, int k) {
114+
int n = nums.length;
115+
int[] s = new int[n];
116+
s[0] = nums[0];
117+
Map<Integer, Integer> right = new HashMap<>();
118+
for (int i = 0; i < n - 1; ++i) {
119+
right.merge(s[i], 1, Integer::sum);
120+
s[i + 1] = s[i] + nums[i + 1];
121+
}
122+
int ans = 0;
123+
if (s[n - 1] % 2 == 0) {
124+
ans = right.getOrDefault(s[n - 1] / 2, 0);
125+
}
126+
Map<Integer, Integer> left = new HashMap<>();
127+
for (int i = 0; i < n; ++i) {
128+
int d = k - nums[i];
129+
if ((s[n - 1] + d) % 2 == 0) {
130+
int t = left.getOrDefault((s[n - 1] + d) / 2, 0) + right.getOrDefault((s[n - 1] - d) / 2, 0);
131+
ans = Math.max(ans, t);
132+
}
133+
left.merge(s[i], 1, Integer::sum);
134+
right.merge(s[i], -1, Integer::sum);
135+
}
136+
return ans;
137+
}
138+
}
139+
```
140+
141+
### **C++**
142+
143+
```cpp
144+
class Solution {
145+
public:
146+
int waysToPartition(vector<int>& nums, int k) {
147+
int n = nums.size();
148+
long long s[n];
149+
s[0] = nums[0];
150+
unordered_map<long long, int> right;
151+
for (int i = 0; i < n - 1; ++i) {
152+
right[s[i]]++;
153+
s[i + 1] = s[i] + nums[i + 1];
154+
}
155+
int ans = 0;
156+
if (s[n - 1] % 2 == 0) {
157+
ans = right[s[n - 1] / 2];
158+
}
159+
unordered_map<long long, int> left;
160+
for (int i = 0; i < n; ++i) {
161+
int d = k - nums[i];
162+
if ((s[n - 1] + d) % 2 == 0) {
163+
int t = left[(s[n - 1] + d) / 2] + right[(s[n - 1] - d) / 2];
164+
ans = max(ans, t);
165+
}
166+
left[s[i]]++;
167+
right[s[i]]--;
168+
}
169+
return ans;
170+
}
171+
};
172+
```
78173
174+
### **Go**
175+
176+
```go
177+
func waysToPartition(nums []int, k int) (ans int) {
178+
n := len(nums)
179+
s := make([]int, n)
180+
s[0] = nums[0]
181+
right := map[int]int{}
182+
for i := range nums[:n-1] {
183+
right[s[i]]++
184+
s[i+1] = s[i] + nums[i+1]
185+
}
186+
if s[n-1]%2 == 0 {
187+
ans = right[s[n-1]/2]
188+
}
189+
left := map[int]int{}
190+
for i, x := range nums {
191+
d := k - x
192+
if (s[n-1]+d)%2 == 0 {
193+
t := left[(s[n-1]+d)/2] + right[(s[n-1]-d)/2]
194+
if ans < t {
195+
ans = t
196+
}
197+
}
198+
left[s[i]]++
199+
right[s[i]]--
200+
}
201+
return
202+
}
79203
```
80204

81205
### **...**

solution/2000-2099/2025.Maximum Number of Ways to Partition an Array/README_EN.md

Lines changed: 113 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,125 @@ There are four ways to partition the array.
6262
### **Python3**
6363

6464
```python
65-
65+
class Solution:
66+
def waysToPartition(self, nums: List[int], k: int) -> int:
67+
n = len(nums)
68+
s = [nums[0]] * n
69+
right = defaultdict(int)
70+
for i in range(1, n):
71+
s[i] = s[i - 1] + nums[i]
72+
right[s[i - 1]] += 1
73+
74+
ans = 0
75+
if s[-1] % 2 == 0:
76+
ans = right[s[-1] // 2]
77+
78+
left = defaultdict(int)
79+
for v, x in zip(s, nums):
80+
d = k - x
81+
if (s[-1] + d) % 2 == 0:
82+
t = left[(s[-1] + d) // 2] + right[(s[-1] - d) // 2]
83+
if ans < t:
84+
ans = t
85+
left[v] += 1
86+
right[v] -= 1
87+
return ans
6688
```
6789

6890
### **Java**
6991

7092
```java
93+
class Solution {
94+
public int waysToPartition(int[] nums, int k) {
95+
int n = nums.length;
96+
int[] s = new int[n];
97+
s[0] = nums[0];
98+
Map<Integer, Integer> right = new HashMap<>();
99+
for (int i = 0; i < n - 1; ++i) {
100+
right.merge(s[i], 1, Integer::sum);
101+
s[i + 1] = s[i] + nums[i + 1];
102+
}
103+
int ans = 0;
104+
if (s[n - 1] % 2 == 0) {
105+
ans = right.getOrDefault(s[n - 1] / 2, 0);
106+
}
107+
Map<Integer, Integer> left = new HashMap<>();
108+
for (int i = 0; i < n; ++i) {
109+
int d = k - nums[i];
110+
if ((s[n - 1] + d) % 2 == 0) {
111+
int t = left.getOrDefault((s[n - 1] + d) / 2, 0) + right.getOrDefault((s[n - 1] - d) / 2, 0);
112+
ans = Math.max(ans, t);
113+
}
114+
left.merge(s[i], 1, Integer::sum);
115+
right.merge(s[i], -1, Integer::sum);
116+
}
117+
return ans;
118+
}
119+
}
120+
```
121+
122+
### **C++**
123+
124+
```cpp
125+
class Solution {
126+
public:
127+
int waysToPartition(vector<int>& nums, int k) {
128+
int n = nums.size();
129+
long long s[n];
130+
s[0] = nums[0];
131+
unordered_map<long long, int> right;
132+
for (int i = 0; i < n - 1; ++i) {
133+
right[s[i]]++;
134+
s[i + 1] = s[i] + nums[i + 1];
135+
}
136+
int ans = 0;
137+
if (s[n - 1] % 2 == 0) {
138+
ans = right[s[n - 1] / 2];
139+
}
140+
unordered_map<long long, int> left;
141+
for (int i = 0; i < n; ++i) {
142+
int d = k - nums[i];
143+
if ((s[n - 1] + d) % 2 == 0) {
144+
int t = left[(s[n - 1] + d) / 2] + right[(s[n - 1] - d) / 2];
145+
ans = max(ans, t);
146+
}
147+
left[s[i]]++;
148+
right[s[i]]--;
149+
}
150+
return ans;
151+
}
152+
};
153+
```
71154
155+
### **Go**
156+
157+
```go
158+
func waysToPartition(nums []int, k int) (ans int) {
159+
n := len(nums)
160+
s := make([]int, n)
161+
s[0] = nums[0]
162+
right := map[int]int{}
163+
for i := range nums[:n-1] {
164+
right[s[i]]++
165+
s[i+1] = s[i] + nums[i+1]
166+
}
167+
if s[n-1]%2 == 0 {
168+
ans = right[s[n-1]/2]
169+
}
170+
left := map[int]int{}
171+
for i, x := range nums {
172+
d := k - x
173+
if (s[n-1]+d)%2 == 0 {
174+
t := left[(s[n-1]+d)/2] + right[(s[n-1]-d)/2]
175+
if ans < t {
176+
ans = t
177+
}
178+
}
179+
left[s[i]]++
180+
right[s[i]]--
181+
}
182+
return
183+
}
72184
```
73185

74186
### **...**
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
class Solution {
2+
public:
3+
int waysToPartition(vector<int>& nums, int k) {
4+
int n = nums.size();
5+
long long s[n];
6+
s[0] = nums[0];
7+
unordered_map<long long, int> right;
8+
for (int i = 0; i < n - 1; ++i) {
9+
right[s[i]]++;
10+
s[i + 1] = s[i] + nums[i + 1];
11+
}
12+
int ans = 0;
13+
if (s[n - 1] % 2 == 0) {
14+
ans = right[s[n - 1] / 2];
15+
}
16+
unordered_map<long long, int> left;
17+
for (int i = 0; i < n; ++i) {
18+
int d = k - nums[i];
19+
if ((s[n - 1] + d) % 2 == 0) {
20+
int t = left[(s[n - 1] + d) / 2] + right[(s[n - 1] - d) / 2];
21+
ans = max(ans, t);
22+
}
23+
left[s[i]]++;
24+
right[s[i]]--;
25+
}
26+
return ans;
27+
}
28+
};
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
func waysToPartition(nums []int, k int) (ans int) {
2+
n := len(nums)
3+
s := make([]int, n)
4+
s[0] = nums[0]
5+
right := map[int]int{}
6+
for i := range nums[:n-1] {
7+
right[s[i]]++
8+
s[i+1] = s[i] + nums[i+1]
9+
}
10+
if s[n-1]%2 == 0 {
11+
ans = right[s[n-1]/2]
12+
}
13+
left := map[int]int{}
14+
for i, x := range nums {
15+
d := k - x
16+
if (s[n-1]+d)%2 == 0 {
17+
t := left[(s[n-1]+d)/2] + right[(s[n-1]-d)/2]
18+
if ans < t {
19+
ans = t
20+
}
21+
}
22+
left[s[i]]++
23+
right[s[i]]--
24+
}
25+
return
26+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
class Solution {
2+
public int waysToPartition(int[] nums, int k) {
3+
int n = nums.length;
4+
int[] s = new int[n];
5+
s[0] = nums[0];
6+
Map<Integer, Integer> right = new HashMap<>();
7+
for (int i = 0; i < n - 1; ++i) {
8+
right.merge(s[i], 1, Integer::sum);
9+
s[i + 1] = s[i] + nums[i + 1];
10+
}
11+
int ans = 0;
12+
if (s[n - 1] % 2 == 0) {
13+
ans = right.getOrDefault(s[n - 1] / 2, 0);
14+
}
15+
Map<Integer, Integer> left = new HashMap<>();
16+
for (int i = 0; i < n; ++i) {
17+
int d = k - nums[i];
18+
if ((s[n - 1] + d) % 2 == 0) {
19+
int t = left.getOrDefault((s[n - 1] + d) / 2, 0) + right.getOrDefault((s[n - 1] - d) / 2, 0);
20+
ans = Math.max(ans, t);
21+
}
22+
left.merge(s[i], 1, Integer::sum);
23+
right.merge(s[i], -1, Integer::sum);
24+
}
25+
return ans;
26+
}
27+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
class Solution:
2+
def waysToPartition(self, nums: List[int], k: int) -> int:
3+
n = len(nums)
4+
s = [nums[0]] * n
5+
right = defaultdict(int)
6+
for i in range(1, n):
7+
s[i] = s[i - 1] + nums[i]
8+
right[s[i - 1]] += 1
9+
10+
ans = 0
11+
if s[-1] % 2 == 0:
12+
ans = right[s[-1] // 2]
13+
14+
left = defaultdict(int)
15+
for v, x in zip(s, nums):
16+
d = k - x
17+
if (s[-1] + d) % 2 == 0:
18+
t = left[(s[-1] + d) // 2] + right[(s[-1] - d) // 2]
19+
if ans < t:
20+
ans = t
21+
left[v] += 1
22+
right[v] -= 1
23+
return ans

0 commit comments

Comments
 (0)