comments | difficulty | edit_url | rating | source | tags | ||||
---|---|---|---|---|---|---|---|---|---|
true |
Medium |
2078 |
Weekly Contest 222 Q3 |
|
A split of an integer array is good if:
- The array is split into three non-empty contiguous subarrays - named
left
,mid
,right
respectively from left to right. - The sum of the elements in
left
is less than or equal to the sum of the elements inmid
, and the sum of the elements inmid
is less than or equal to the sum of the elements inright
.
Given nums
, an array of non-negative integers, return the number of good ways to split nums
. As the number may be too large, return it modulo 109 + 7
.
Example 1:
Input: nums = [1,1,1] Output: 1 Explanation: The only good way to split nums is [1] [1] [1].
Example 2:
Input: nums = [1,2,2,2,5,0] Output: 3 Explanation: There are three good ways of splitting nums: [1] [2] [2,2,5,0] [1] [2,2] [2,5,0] [1,2] [2,2] [5,0]
Example 3:
Input: nums = [3,2,1] Output: 0 Explanation: There is no good way to split nums.
Constraints:
3 <= nums.length <= 105
0 <= nums[i] <= 104
First, we preprocess the prefix sum array
Since all elements of the array
We enumerate the index left
subarray can reach in the range mid
subarray split by binary search, denoted as
In the binary search details, the subarray split must satisfy
Finally, return the number of schemes modulo
The time complexity is
class Solution:
def waysToSplit(self, nums: List[int]) -> int:
mod = 10**9 + 7
s = list(accumulate(nums))
ans, n = 0, len(nums)
for i in range(n - 2):
j = bisect_left(s, s[i] << 1, i + 1, n - 1)
k = bisect_right(s, (s[-1] + s[i]) >> 1, j, n - 1)
ans += k - j
return ans % mod
class Solution {
private static final int MOD = (int) 1e9 + 7;
public int waysToSplit(int[] nums) {
int n = nums.length;
int[] s = new int[n];
s[0] = nums[0];
for (int i = 1; i < n; ++i) {
s[i] = s[i - 1] + nums[i];
}
int ans = 0;
for (int i = 0; i < n - 2; ++i) {
int j = search(s, s[i] << 1, i + 1, n - 1);
int k = search(s, ((s[n - 1] + s[i]) >> 1) + 1, j, n - 1);
ans = (ans + k - j) % MOD;
}
return ans;
}
private int search(int[] s, int x, int left, int right) {
while (left < right) {
int mid = (left + right) >> 1;
if (s[mid] >= x) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
}
}
class Solution {
public:
const int mod = 1e9 + 7;
int waysToSplit(vector<int>& nums) {
int n = nums.size();
vector<int> s(n, nums[0]);
for (int i = 1; i < n; ++i) s[i] = s[i - 1] + nums[i];
int ans = 0;
for (int i = 0; i < n - 2; ++i) {
int j = lower_bound(s.begin() + i + 1, s.begin() + n - 1, s[i] << 1) - s.begin();
int k = upper_bound(s.begin() + j, s.begin() + n - 1, (s[n - 1] + s[i]) >> 1) - s.begin();
ans = (ans + k - j) % mod;
}
return ans;
}
};
func waysToSplit(nums []int) (ans int) {
const mod int = 1e9 + 7
n := len(nums)
s := make([]int, n)
s[0] = nums[0]
for i := 1; i < n; i++ {
s[i] = s[i-1] + nums[i]
}
for i := 0; i < n-2; i++ {
j := sort.Search(n-1, func(h int) bool { return h > i && s[h] >= (s[i]<<1) })
k := sort.Search(n-1, func(h int) bool { return h >= j && s[h] > (s[n-1]+s[i])>>1 })
ans = (ans + k - j) % mod
}
return
}
/**
* @param {number[]} nums
* @return {number}
*/
var waysToSplit = function (nums) {
const mod = 1e9 + 7;
const n = nums.length;
const s = new Array(n).fill(nums[0]);
for (let i = 1; i < n; ++i) {
s[i] = s[i - 1] + nums[i];
}
function search(s, x, left, right) {
while (left < right) {
const mid = (left + right) >> 1;
if (s[mid] >= x) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
}
let ans = 0;
for (let i = 0; i < n - 2; ++i) {
const j = search(s, s[i] << 1, i + 1, n - 1);
const k = search(s, ((s[n - 1] + s[i]) >> 1) + 1, j, n - 1);
ans = (ans + k - j) % mod;
}
return ans;
};