📜  Kth正数的连续子数组的最小和(1)

📅  最后修改于: 2023-12-03 14:43:42.930000             🧑  作者: Mango

Kth正数的连续子数组的最小和

问题描述

给定一个正整数数组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小的连续子数组的最小和。虽然时间复杂度比较高,但是在数据规模较大时,比暴力枚举有更好的表现。