📅  最后修改于: 2023-12-03 14:43:42.930000             🧑  作者: Mango
给定一个正整数数组nums和一个整数k,请找出该数组中第k小的连续子数组的最小和。
由于该问题要求第k小的连续子数组的最小和,我们可以先对所有的连续子数组的和进行排序,然后取出第k个最小的和即可。时间复杂度为O(n^3logn),空间复杂度为O(n)。
class Solution:
def kthSmallestSubarraySum(self, nums: List[int], k: int) -> int:
sub_sums = []
for i in range(len(nums)):
for j in range(i + 1, len(nums) + 1):
sub_sums.append(sum(nums[i:j]))
sub_sums.sort()
return sub_sums[k - 1]
由于第k小的和必定在所有连续子数组的和的最大值和最小值之间,我们可以使用二分查找来缩小范围。时间复杂度为O(nlognlogmax),其中max为nums数组中元素的最大值,空间复杂度为O(1)。
class Solution:
def kthSmallestSubarraySum(self, nums: List[int], k: int) -> int:
def countSubarrays(mid: int) -> int:
count = 0
left = 0
total = 0
for right in range(len(nums)):
total += nums[right]
while total > mid:
total -= nums[left]
left += 1
count += right - left + 1
return count
left, right = min(nums), sum(nums)
while left < right:
mid = (left + right) // 2
if countSubarrays(mid) < k:
left = mid + 1
else:
right = mid
return left
暴力枚举虽然容易实现,但是时间复杂度太高。而二分查找则需要对子数组和的范围进行二分,然后查看数组中有多少个子数组满足要求,最后根据二分结果返回第k小的连续子数组的最小和。虽然时间复杂度比较高,但是在数据规模较大时,比暴力枚举有更好的表现。