此题解采用二分查找的方法。首先定义二分查找的左边界为数组中的最大值,右边界为数组所有元素之和。二分查找的目标是找到最小的最大子数组和,使得数组可以被分割成k个子数组。在二分查找的每一步中,判断当前的中间值是否可以将数组分割成k个子数组,如果可以,则右边界更新为中间值;如果不可以,则左边界更新为中间值加一。最终二分查找的结果即为答案。判断是否可以分割成k个子数组的方法是,遍历数组,累加数组元素,如果当前子数组和超过了最大允许值,则开始一个新的子数组,同时子数组的数量加一。如果最终子数组的数量大于k,则说明无法分割,返回False;否则返回True。
时间复杂度: O(n*log(sum-max)),其中sum为数组元素之和,max为数组中的最大值;极端情况下退化为O(n)
空间复杂度: O(1)
class Solution:
def splitArray(self, nums: List[int], k: int) -> int:
max_val = max(nums) # 数组最大值作为二分查找左边界
array_sum = sum(nums) # 数组和作为二分查找右边界
left = max_val
right = array_sum
while right > left:
mid = (right-left) // 2 + left # 计算中间值
if self.canSplit(nums, k, mid): # 判断中间值是否可以分割
right = mid # 可以分割,更新右边界
else:
left = mid + 1 # 不可以分割,更新左边界
return left # 二分查找的最终结果
def canSplit(self, nums, k, max_val):
count = 1 # 当前子数组计数
array_sum = 0 # 当前子数组和
for num in nums:
array_sum += num # 累加当前元素到子数组
if array_sum > max_val: # 子数组和超过最大允许值
count += 1 # 新开一个子数组
array_sum = num # 重置子数组和为当前元素
if count > k: # 子数组数量超过k
return False # 无法分割
return True # 可以分割