1711 將陣列分成三個子陣列的方案數
阿新 • • 發佈:2021-01-04
技術標籤:LeetCode
題目描述:
我們稱一個分割整數陣列的方案是 好的 ,當它滿足:
陣列被分成三個 非空 連續子陣列,從左至右分別命名為 left , mid , right 。
left 中元素和小於等於 mid 中元素和,mid 中元素和小於等於 right 中元素和。
給你一個 非負 整數陣列 nums ,請你返回 好的 分割 nums 方案數目。由於答案可能會很大,請你將結果對 109 + 7 取餘後返回。
示例 1:
輸入:nums = [1,1,1]
輸出:1
解釋:唯一一種好的分割方案是將 nums 分成 [1] [1] [1] 。
示例 2:
輸入:nums = [1,2,2,2,5,0]
解釋:nums 總共有 3 種好的分割方案:
[1] [2] [2,2,5,0]
[1] [2,2] [2,5,0]
[1,2] [2,2] [5,0]
示例 3:
輸入:nums = [3,2,1]
輸出:0
解釋:沒有好的分割方案。
提示:
3 <= nums.length <= 105
0 <= nums[i] <= 104
方法1:
主要思路:解題彙總連結
(1)字首和+二分;
(2)先統計出原陣列的字首和;
(3)固定左邊的子陣列,再使用二分,找出滿足要求的中間陣列中,中間陣列的右邊界最小的取值;
(4)再使用二分,找出滿足要求的中間陣列中,中間陣列的右邊界最大的取值;
class Solution {
public:
int waysToSplit(vector<int>& nums) {
int len=nums.size();
vector<long long> sum_sub(len+1,0);
long long res=0;
for(int i=0;i<len;++i){//統計字首和
sum_sub[i+1]=nums[i]+sum_sub[i];
}
int end_sum=sum_sub.back()/3;//按照三個陣列的關係,則左陣列的最大和
for(int i=1;i<len;++i){
if(sum_sub[i]>end_sum){//超過該值,則不可能有滿足要求 的方案
break;
}
//統計出中間陣列的右邊界的最小值
int left=i+1,right=len;//
while(left<right){
int mid=left+(right-left)/2;
if(sum_sub[i]>sum_sub[mid]-sum_sub[i]){
left=mid+1;
}
else{
right=mid;
}
}
int split1=right;
//找出滿足要求的中間陣列的右邊界的最大取值
left=split1;
right=len;
while(left<right){
int mid=left+(right-left)/2;
if(sum_sub[mid]-sum_sub[i]<=sum_sub[len]-sum_sub[mid]){
left=mid+1;
}
else{
right=mid;
}
}
int split2=left-1;
//當前方案數
res+=split2-split1+1;
res%=1000000007;
}
return res%1000000007;
}
};