题目:原题链接(中等)
标签:双指针、二分查找
解法 | 时间复杂度 | 空间复杂度 | 执行用时 |
---|---|---|---|
Ans 1 (Python) | O ( N l o g N ) O(NlogN) O(NlogN) | O ( N ) O(N) O(N) | 652ms (80.93%) |
Ans 2 (Python) | |||
Ans 3 (Python) |
解法一:
class Solution:
# O(NlogN)
_MOD = 10 ** 9 + 7
def waysToSplit(self, nums: List[int]) -> int:
total = sum(nums)
# 处理全为0的特殊情况
if total == 0:
size = len(nums)
return ((size - 1) * (size - 2) // 2) % self._MOD
# 计算前缀和
prefix = []
for num in nums:
if not prefix:
prefix.append(num)
else:
prefix.append(prefix[-1] + num)
# print(prefix)
# 首先找到mid和right的分界点的最右侧的可能
d2 = bisect.bisect_right(prefix, math.ceil(total * 2 / 3))
# print("D2(max):", d2)
ans = 0
# 逐渐向左迭代d2(d2位right的最左侧元素的下标)
while d2 >= 2: # 如果小于等于2则左边只有一个点,不够分
v3 = total - prefix[d2 - 1] # 计算right部分的和
surplus = prefix[d2 - 1] # 计算当前left和mid部分的总和
# print("D2,V3:", d2, v3)
# 找到left和mid的分界点的最左侧的位置(mid部分的和小于等于right部分的和)
v2_max = v3
v1_min = surplus - v2_max
d1_min = max(1, bisect.bisect_left(prefix, v1_min)) # 处理可能包含0的情况
if prefix[d1_min - 1] < v1_min:
d1_min += 1
# 找到left和mid的分界点的最右侧的位置(left部分的和小于等于mid部分的和)
v1_max = math.floor(surplus / 2)
d1_max = bisect.bisect_right(prefix, v1_max) # 处理可能包含0的情况
# if d1_max > 1 and prefix[d1_max - 1] == v1_max:
# d1_max -= 1
# print("V1(min):", v1_min, "V1(max):", v1_max, "D1(min):", d1_min, "D1(max):", d1_max)
# 累加结果总和
if v1_min <= v1_max:
ans += d1_max - d1_min + 1
d2 -= 1
return ans % self._MOD