Skip to content

Commit a85856a

Browse files
committed
feat: add solutions to lc problem: No.0410
No.0410.Split Array Largest Sum
1 parent 1a3880f commit a85856a

File tree

7 files changed

+282
-224
lines changed

7 files changed

+282
-224
lines changed

solution/0400-0499/0410.Split Array Largest Sum/README.md

+100-75
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,15 @@
5050

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

53-
二分查找
53+
**方法一:二分查找**
5454

55-
二分枚举**子数组的和的最大值**,找到满足条件的最小值。
55+
我们注意到,当子数组的和的最大值越大,子数组的个数越少,当存在一个满足条件的子数组和的最大值时,那么比这个最大值更大的子数组和的最大值一定也满足条件。也就是说,我们可以对子数组和的最大值进行二分查找,找到满足条件的最小值。
56+
57+
我们定义二分查找的左边界 $left = max(nums)$,右边界 $right = sum(nums)$,然后对于二分查找的每一步,我们取中间值 $mid = (left + right) / 2$,然后判断是否存在一个分割方式,使得子数组的和的最大值不超过 $mid$,如果存在,则说明 $mid$ 可能是满足条件的最小值,因此我们将右边界调整为 $mid$,否则我们将左边界调整为 $mid + 1$。
58+
59+
我们如何判断是否存在一个分割方式,使得子数组的和的最大值不超过 $mid$ 呢?我们可以使用贪心的方法,从左到右遍历数组,将数组中的元素依次加入到子数组中,如果当前子数组的和大于 $mid$,则我们将当前元素加入到下一个子数组中。如果我们能够将数组分割成不超过 $k$ 个子数组,且每个子数组的和的最大值不超过 $mid$,则说明 $mid$ 是满足条件的最小值,否则 $mid$ 不是满足条件的最小值。
60+
61+
时间复杂度 $O(n \times \log m),空间复杂度 O(1)$。其中 $n$ 和 $m$ 分别是数组的长度和数组所有元素的和。
5662

5763
<!-- tabs:start -->
5864

@@ -62,25 +68,18 @@
6268

6369
```python
6470
class Solution:
65-
def splitArray(self, nums: List[int], m: int) -> int:
66-
def check(x):
67-
s, cnt = 0, 1
68-
for num in nums:
69-
if s + num > x:
71+
def splitArray(self, nums: List[int], k: int) -> int:
72+
def check(mx):
73+
s, cnt = inf, 0
74+
for x in nums:
75+
s += x
76+
if s > mx:
77+
s = x
7078
cnt += 1
71-
s = num
72-
else:
73-
s += num
74-
return cnt <= m
79+
return cnt <= k
7580

7681
left, right = max(nums), sum(nums)
77-
while left < right:
78-
mid = (left + right) >> 1
79-
if check(mid):
80-
right = mid
81-
else:
82-
left = mid + 1
83-
return left
82+
return left + bisect_left(range(left, right + 1), True, key=check)
8483
```
8584

8685
### **Java**
@@ -89,15 +88,15 @@ class Solution:
8988

9089
```java
9190
class Solution {
92-
public int splitArray(int[] nums, int m) {
93-
int mx = -1;
94-
for (int num : nums) {
95-
mx = Math.max(mx, num);
91+
public int splitArray(int[] nums, int k) {
92+
int left = 0, right = 0;
93+
for (int x : nums) {
94+
left = Math.max(left, x);
95+
right += x;
9696
}
97-
int left = mx, right = (int) 1e9;
9897
while (left < right) {
9998
int mid = (left + right) >> 1;
100-
if (check(nums, m, mid)) {
99+
if (check(nums, mid, k)) {
101100
right = mid;
102101
} else {
103102
left = mid + 1;
@@ -106,17 +105,16 @@ class Solution {
106105
return left;
107106
}
108107

109-
private boolean check(int[] nums, int m, int x) {
110-
int s = 0, cnt = 1;
111-
for (int num : nums) {
112-
if (s + num > x) {
108+
private boolean check(int[] nums, int mx, int k) {
109+
int s = 1 << 30, cnt = 0;
110+
for (int x : nums) {
111+
s += x;
112+
if (s > mx) {
113113
++cnt;
114-
s = num;
115-
} else {
116-
s += num;
114+
s = x;
117115
}
118116
}
119-
return cnt <= m;
117+
return cnt <= k;
120118
}
121119
}
122120
```
@@ -126,29 +124,32 @@ class Solution {
126124
```cpp
127125
class Solution {
128126
public:
129-
int splitArray(vector<int>& nums, int m) {
130-
int left = *max_element(nums.begin(), nums.end()), right = (int)1e9;
127+
int splitArray(vector<int>& nums, int k) {
128+
int left = 0, right = 0;
129+
for (int& x : nums) {
130+
left = max(left, x);
131+
right += x;
132+
}
133+
auto check = [&](int mx) {
134+
int s = 1 << 30, cnt = 0;
135+
for (int& x : nums) {
136+
s += x;
137+
if (s > mx) {
138+
s = x;
139+
++cnt;
140+
}
141+
}
142+
return cnt <= k;
143+
};
131144
while (left < right) {
132-
int mid = left + right >> 1;
133-
if (check(nums, m, mid))
145+
int mid = (left + right) >> 1;
146+
if (check(mid)) {
134147
right = mid;
135-
else
136-
left = mid + 1;
137-
}
138-
return left;
139-
}
140-
141-
bool check(vector<int>& nums, int m, int x) {
142-
int s = 0, cnt = 1;
143-
for (int num : nums) {
144-
if (s + num > x) {
145-
++cnt;
146-
s = num;
147148
} else {
148-
s += num;
149+
left = mid + 1;
149150
}
150151
}
151-
return cnt <= m;
152+
return left;
152153
}
153154
};
154155
```
@@ -157,33 +158,23 @@ public:
157158
158159
```go
159160
func splitArray(nums []int, k int) int {
160-
mx := -1
161-
for _, num := range nums {
162-
mx = max(mx, num)
161+
left, right := 0, 0
162+
for _, x := range nums {
163+
left = max(left, x)
164+
right += x
163165
}
164-
left, right := mx, int(1e9)
165-
for left < right {
166-
mid := (left + right) >> 1
167-
if check(nums, k, mid) {
168-
right = mid
169-
} else {
170-
left = mid + 1
166+
return left + sort.Search(right-left, func(mx int) bool {
167+
mx += left
168+
s, cnt := 1<<30, 0
169+
for _, x := range nums {
170+
s += x
171+
if s > mx {
172+
s = x
173+
cnt++
174+
}
171175
}
172-
}
173-
return left
174-
}
175-
176-
func check(nums []int, k, x int) bool {
177-
s, cnt := 0, 1
178-
for _, num := range nums {
179-
if s+num > x {
180-
cnt++
181-
s = num
182-
} else {
183-
s += num
184-
}
185-
}
186-
return cnt <= k
176+
return cnt <= k
177+
})
187178
}
188179
189180
func max(a, b int) int {
@@ -194,6 +185,40 @@ func max(a, b int) int {
194185
}
195186
```
196187

188+
### **TypeScript**
189+
190+
```ts
191+
function splitArray(nums: number[], k: number): number {
192+
let left = 0;
193+
let right = 0;
194+
for (const x of nums) {
195+
left = Math.max(left, x);
196+
right += x;
197+
}
198+
const check = (mx: number) => {
199+
let s = 1 << 30;
200+
let cnt = 0;
201+
for (const x of nums) {
202+
s += x;
203+
if (s > mx) {
204+
s = x;
205+
++cnt;
206+
}
207+
}
208+
return cnt <= k;
209+
};
210+
while (left < right) {
211+
const mid = (left + right) >> 1;
212+
if (check(mid)) {
213+
right = mid;
214+
} else {
215+
left = mid + 1;
216+
}
217+
}
218+
return left;
219+
}
220+
```
221+
197222
### **...**
198223

199224
```

0 commit comments

Comments
 (0)