题目不好整啊,开始以为是DP,看了HInt,后来看了大神写的二分查找的答案。首先建立一个前缀和序列。后开始遍历第一段sub array的截止位置,由题目限制可知,其最大的截止位置带来的前缀和要小于等于全nums的和,也就是前缀和序列最后一位。好了,知道第一个分割点在哪里,就可以对后面这段做分割了。在第一段知道截断位置的前提下,中间这段的和,最小也需要是第一段subarray的和的两倍。由此可以得到第二段suabarray截断点的最小位置。而其最大位置,可以这样求的,第一段的截止位置的和 与全nums的和的中间值,在第一段截断后的后面这一大段所能排到的位置,这样,保证了我们作出的第二段的截断点右边的subarray的和不会大于剩下的这一大段的和的一半。同时,要处理特殊情况就是全部数字一样时,则第二段的最大位置可能会大于len(nums)。同样,需要注意最大的第二段截断位置的subarray的值如果因为设置了,其位置必须大于最小的截断位置时而带来所得位置的subaray的值大于了剩下一大段的和的一半,这种情况需要特判。
class Solution:
def waysToSplit(self, nums: List[int]) -> int:
prefix = [nums[0]]
for i in range(1, len(nums)):
prefix.append(prefix[-1]+ nums[i])
res = 0
Mod = 10**9+7
for i in range(len(prefix)):
firstseg = prefix[i]
if firstseg*3 > prefix[-1]:break
second_first_seg = firstseg*2
second_first_seg_pos = bisect.bisect_left(prefix, second_first_seg, i+1)
second_second_seg = (prefix[i] + prefix[-1])//2
second_second_seg_pos = bisect.bisect_right(prefix, second_second_seg, second_first_seg_pos+1)
if second_second_seg_pos > len(nums) or prefix[second_second_seg_pos-1] > second_second_seg:continue
res = (res + (min(len(nums)-1, second_second_seg_pos) - second_first_seg_pos))%Mod
return res