Skip to content

Commit 2c34080

Browse files
committed
feat: add solutions to lc problem: No.1712
No.1712.Ways to Split Array Into Three Subarrays
1 parent cf8dce0 commit 2c34080

File tree

6 files changed

+253
-165
lines changed

6 files changed

+253
-165
lines changed

solution/1700-1799/1712.Ways to Split Array Into Three Subarrays/README.md

+93-55
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@
5555

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

58+
**方法一:双指针 + 二分查找**
59+
60+
计算数组 `nums` 的前缀和 `s`。由于 `nums[i]` 是非负整数,可以得知 `s` 是一个单调递增数组。
61+
62+
我们枚举 `left` 子数组所能到达的下标,记为 `i`。然后二分查找 `mid` 子数组分割的合理范围,记为 `[j0, j1)`,累加方案数 `j1-j0`。注意答案取模操作。
63+
64+
时间复杂度 $O(n\log n)$,空间复杂度 $O(n)$,其中 $n$ 是数组的长度。
65+
5866
<!-- tabs:start -->
5967

6068
### **Python3**
@@ -64,32 +72,14 @@
6472
```python
6573
class Solution:
6674
def waysToSplit(self, nums: List[int]) -> int:
67-
mod = 1e9 + 7
68-
n = len(nums)
69-
pre = [0] * (n + 1)
70-
for i in range(1, n + 1):
71-
pre[i] = pre[i - 1] + nums[i - 1]
72-
ans = 0
73-
for i in range(1, n - 1):
74-
if pre[i] * 3 > pre[n]:
75-
break
76-
left, right = i + 1, n - 1
77-
while left < right:
78-
mid = (left + right + 1) >> 1
79-
if pre[mid] - pre[i] <= pre[n] - pre[mid]:
80-
left = mid
81-
else:
82-
right = mid - 1
83-
mid_right = left
84-
left, right = i + 1, n - 1
85-
while left < right:
86-
mid = (left + right) >> 1
87-
if pre[mid] - pre[i] >= pre[i]:
88-
right = mid
89-
else:
90-
left = mid + 1
91-
ans += (mid_right - left + 1) % mod
92-
return int(ans % mod)
75+
mod = 10**9 + 7
76+
s = list(accumulate(nums))
77+
ans, n = 0, len(nums)
78+
for i in range(n - 2):
79+
j0 = bisect_left(s, s[i] * 2, i + 1, n - 1)
80+
j1 = bisect_right(s, (s[-1] + s[i]) // 2, j0, n - 1)
81+
ans += j1 - j0
82+
return ans % mod
9383
```
9484

9585
### **Java**
@@ -98,44 +88,92 @@ class Solution:
9888

9989
```java
10090
class Solution {
91+
private static final int MOD = (int) 1e9 + 7;
92+
10193
public int waysToSplit(int[] nums) {
102-
double mod = 1e9 + 7;
10394
int n = nums.length;
104-
long[] pre = new long[n + 1];
105-
for (int i = 1; i < n + 1; i++) {
106-
pre[i] = pre[i - 1] + nums[i - 1];
95+
int[] s = new int[n];
96+
s[0] = nums[0];
97+
for (int i = 1; i < n; ++i) {
98+
s[i] = s[i - 1] + nums[i];
10799
}
108-
double ans = 0;
109-
for (int i = 1; i < n - 1; i++) {
110-
if (pre[i] * 3 > pre[n]) {
111-
break;
112-
}
113-
int left = i + 1, right = n - 1;
114-
while (left < right) {
115-
int mid = (left + right + 1) >> 1;
116-
if (pre[mid] - pre[i] <= pre[n] - pre[mid]) {
117-
left = mid;
118-
} else {
119-
right = mid - 1;
120-
}
121-
}
122-
int midRight = left;
123-
left = i + 1; right = n - 1;
124-
while (left < right) {
125-
int mid = (left + right) >> 1;
126-
if (pre[mid] - pre[i] >= pre[i]) {
127-
right = mid;
128-
} else {
129-
left = mid + 1;
130-
}
100+
int ans = 0;
101+
for (int i = 0; i < n - 2; ++i) {
102+
int j0 = lowerBound(s, s[i] * 2, i + 1, n - 1);
103+
int j1 = lowerBound(s, (s[i] + s[n - 1]) / 2 + 1, j0, n - 1);
104+
ans = (ans + j1 - j0) % MOD;
105+
}
106+
return ans;
107+
}
108+
109+
private int lowerBound(int[] s, int x, int left, int right) {
110+
while (left < right) {
111+
int mid = (left + right) >> 1;
112+
if (s[mid] >= x) {
113+
right = mid;
114+
} else {
115+
left = mid + 1;
131116
}
132-
ans += (midRight - left + 1) % mod;
133117
}
134-
return (int) (ans % mod);
118+
return left;
135119
}
136120
}
137121
```
138122

123+
### **C++**
124+
125+
```cpp
126+
class Solution {
127+
public:
128+
int waysToSplit(vector<int>& nums) {
129+
int n = nums.size();
130+
vector<int> s(n, nums[0]);
131+
for (int i = 1; i < n; ++i) s[i] = s[i - 1] + nums[i];
132+
int ans = 0;
133+
int mod = 1e9 + 7;
134+
for (int i = 0; i < n - 2; ++i) {
135+
int j0 = lower_bound(s.begin() + i + 1, s.begin() + n - 1, s[i] * 2) - s.begin();
136+
int j1 = upper_bound(s.begin() + j0, s.begin() + n - 1, (s[i] + s[n - 1]) / 2) - s.begin();
137+
ans = (ans + j1 - j0) % mod;
138+
}
139+
return ans;
140+
}
141+
};
142+
```
143+
144+
### ****
145+
146+
```go
147+
func waysToSplit(nums []int) int {
148+
search := func(s []int, x, left, right int) int {
149+
for left < right {
150+
mid := (left + right) >> 1
151+
if s[mid] >= x {
152+
right = mid
153+
} else {
154+
left = mid + 1
155+
}
156+
}
157+
return left
158+
}
159+
var mod int = 1e9 + 7
160+
n := len(nums)
161+
s := make([]int, n)
162+
s[0] = nums[0]
163+
for i := 1; i < n; i++ {
164+
s[i] = s[i-1] + nums[i]
165+
}
166+
ans := 0
167+
for i := 0; i < n-2; i++ {
168+
j0 := search(s, s[i]*2, i+1, n-1)
169+
j1 := search(s, (s[i]+s[n-1])/2+1, j0, n-1)
170+
ans += j1 - j0
171+
}
172+
ans %= mod
173+
return ans
174+
}
175+
```
176+
139177
### **...**
140178

141179
```

solution/1700-1799/1712.Ways to Split Array Into Three Subarrays/README_EN.md

+85-55
Original file line numberDiff line numberDiff line change
@@ -56,73 +56,103 @@
5656
```python
5757
class Solution:
5858
def waysToSplit(self, nums: List[int]) -> int:
59-
mod = 1e9 + 7
60-
n = len(nums)
61-
pre = [0] * (n + 1)
62-
for i in range(1, n + 1):
63-
pre[i] = pre[i - 1] + nums[i - 1]
64-
ans = 0
65-
for i in range(1, n - 1):
66-
if pre[i] * 3 > pre[n]:
67-
break
68-
left, right = i + 1, n - 1
69-
while left < right:
70-
mid = (left + right + 1) >> 1
71-
if pre[mid] - pre[i] <= pre[n] - pre[mid]:
72-
left = mid
73-
else:
74-
right = mid - 1
75-
mid_right = left
76-
left, right = i + 1, n - 1
77-
while left < right:
78-
mid = (left + right) >> 1
79-
if pre[mid] - pre[i] >= pre[i]:
80-
right = mid
81-
else:
82-
left = mid + 1
83-
ans += (mid_right - left + 1) % mod
84-
return int(ans % mod)
59+
mod = 10**9 + 7
60+
s = list(accumulate(nums))
61+
ans, n = 0, len(nums)
62+
for i in range(n - 2):
63+
j0 = bisect_left(s, s[i] * 2, i + 1, n - 1)
64+
j1 = bisect_right(s, (s[-1] + s[i]) // 2, j0, n - 1)
65+
ans += j1 - j0
66+
return ans % mod
8567
```
8668

8769
### **Java**
8870

8971
```java
9072
class Solution {
73+
private static final int MOD = (int) 1e9 + 7;
74+
9175
public int waysToSplit(int[] nums) {
92-
double mod = 1e9 + 7;
9376
int n = nums.length;
94-
long[] pre = new long[n + 1];
95-
for (int i = 1; i < n + 1; i++) {
96-
pre[i] = pre[i - 1] + nums[i - 1];
77+
int[] s = new int[n];
78+
s[0] = nums[0];
79+
for (int i = 1; i < n; ++i) {
80+
s[i] = s[i - 1] + nums[i];
9781
}
98-
double ans = 0;
99-
for (int i = 1; i < n - 1; i++) {
100-
if (pre[i] * 3 > pre[n]) {
101-
break;
102-
}
103-
int left = i + 1, right = n - 1;
104-
while (left < right) {
105-
int mid = (left + right + 1) >> 1;
106-
if (pre[mid] - pre[i] <= pre[n] - pre[mid]) {
107-
left = mid;
108-
} else {
109-
right = mid - 1;
110-
}
111-
}
112-
int midRight = left;
113-
left = i + 1; right = n - 1;
114-
while (left < right) {
115-
int mid = (left + right) >> 1;
116-
if (pre[mid] - pre[i] >= pre[i]) {
117-
right = mid;
118-
} else {
119-
left = mid + 1;
120-
}
82+
int ans = 0;
83+
for (int i = 0; i < n - 2; ++i) {
84+
int j0 = lowerBound(s, s[i] * 2, i + 1, n - 1);
85+
int j1 = lowerBound(s, (s[i] + s[n - 1]) / 2 + 1, j0, n - 1);
86+
ans = (ans + j1 - j0) % MOD;
87+
}
88+
return ans;
89+
}
90+
91+
private int lowerBound(int[] s, int x, int left, int right) {
92+
while (left < right) {
93+
int mid = (left + right) >> 1;
94+
if (s[mid] >= x) {
95+
right = mid;
96+
} else {
97+
left = mid + 1;
12198
}
122-
ans += (midRight - left + 1) % mod;
12399
}
124-
return (int) (ans % mod);
100+
return left;
101+
}
102+
}
103+
```
104+
105+
### **C++**
106+
107+
```cpp
108+
class Solution {
109+
public:
110+
int waysToSplit(vector<int>& nums) {
111+
int n = nums.size();
112+
vector<int> s(n, nums[0]);
113+
for (int i = 1; i < n; ++i) s[i] = s[i - 1] + nums[i];
114+
int ans = 0;
115+
int mod = 1e9 + 7;
116+
for (int i = 0; i < n - 2; ++i) {
117+
int j0 = lower_bound(s.begin() + i + 1, s.begin() + n - 1, s[i] * 2) - s.begin();
118+
int j1 = upper_bound(s.begin() + j0, s.begin() + n - 1, (s[i] + s[n - 1]) / 2) - s.begin();
119+
ans = (ans + j1 - j0) % mod;
120+
}
121+
return ans;
125122
}
123+
};
124+
```
125+
126+
### ****
127+
128+
```go
129+
func waysToSplit(nums []int) int {
130+
search := func(s []int, x, left, right int) int {
131+
for left < right {
132+
mid := (left + right) >> 1
133+
if s[mid] >= x {
134+
right = mid
135+
} else {
136+
left = mid + 1
137+
}
138+
}
139+
return left
140+
}
141+
var mod int = 1e9 + 7
142+
n := len(nums)
143+
s := make([]int, n)
144+
s[0] = nums[0]
145+
for i := 1; i < n; i++ {
146+
s[i] = s[i-1] + nums[i]
147+
}
148+
ans := 0
149+
for i := 0; i < n-2; i++ {
150+
j0 := search(s, s[i]*2, i+1, n-1)
151+
j1 := search(s, (s[i]+s[n-1])/2+1, j0, n-1)
152+
ans += j1 - j0
153+
}
154+
ans %= mod
155+
return ans
126156
}
127157
```
128158

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
class Solution {
2+
public:
3+
int waysToSplit(vector<int>& nums) {
4+
int n = nums.size();
5+
vector<int> s(n, nums[0]);
6+
for (int i = 1; i < n; ++i) s[i] = s[i - 1] + nums[i];
7+
int ans = 0;
8+
int mod = 1e9 + 7;
9+
for (int i = 0; i < n - 2; ++i) {
10+
int j0 = lower_bound(s.begin() + i + 1, s.begin() + n - 1, s[i] * 2) - s.begin();
11+
int j1 = upper_bound(s.begin() + j0, s.begin() + n - 1, (s[i] + s[n - 1]) / 2) - s.begin();
12+
ans = (ans + j1 - j0) % mod;
13+
}
14+
return ans;
15+
}
16+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
func waysToSplit(nums []int) int {
2+
search := func(s []int, x, left, right int) int {
3+
for left < right {
4+
mid := (left + right) >> 1
5+
if s[mid] >= x {
6+
right = mid
7+
} else {
8+
left = mid + 1
9+
}
10+
}
11+
return left
12+
}
13+
var mod int = 1e9 + 7
14+
n := len(nums)
15+
s := make([]int, n)
16+
s[0] = nums[0]
17+
for i := 1; i < n; i++ {
18+
s[i] = s[i-1] + nums[i]
19+
}
20+
ans := 0
21+
for i := 0; i < n-2; i++ {
22+
j0 := search(s, s[i]*2, i+1, n-1)
23+
j1 := search(s, (s[i]+s[n-1])/2+1, j0, n-1)
24+
ans += j1 - j0
25+
}
26+
ans %= mod
27+
return ans
28+
}

0 commit comments

Comments
 (0)