862. 和至少为 K 的最短子数组

2022/10/29 leetcode 共 1511 字,约 5 分钟

title

problem link

给你一个整数数组 nums 和一个整数 k ,找出 nums 中和至少为 k 的 最短非空子数组 ,并返回该子数组的长度。如果不存在这样的 子数组 ,返回 -1 。

子数组 是数组中 连续 的一部分。

示例 1:

输入:nums = [1], k = 1
输出:1

示例 2:

输入:nums = [1,2], k = 4
输出:-1

示例 3:

输入:nums = [2,-1,2], k = 3
输出:3

提示:

  • 1 <= nums.length <= 105
  • -105 <= nums[i] <= 105
  • 1 <= k <= 109

solution

单调队列

'''
主要是去除无用数据,维护右端点
可以单调栈二分,也可以单调队列
参考: https://leetcode.cn/problems/shortest-subarray-with-sum-at-least-k/solution/liang-zhang-tu-miao-dong-dan-diao-dui-li-9fvh/
'''

class Solution:
    def shortestSubarray(self, nums: List[int], k: int) -> int:
        ans = float('inf')
        n = len(nums)
        pre = [0]
        for v in nums:
            pre.append(pre[-1] + v)
        import collections
        q = collections.deque()
        # 单调队列,j< i, 向右, 如果s[i] - s[j] >= k, j则不会再作为可作为答案的左端点了; 递增队列 对于s[j] >= s[i], 则j也可以舍弃
        for i, v in enumerate(pre):
            while q and pre[q[-1]] >= v:
                q.pop()
            q.append(i)
            while q and v - pre[q[0]] >= k:
                ans = min(ans, i - q[0])
                q.popleft()
        return ans if ans != float('inf') else -1


# 单调栈 + 二分
class BinarySearch:
    # If you wanna binary search big integer, plz set data range, which can be used as same as big integer low and high
    # find the first index that value >= val
    def bisect_left(data, val, l=None, r=None, key=None):
        if l is None or r is None:
            l, r = 0, len(data) - 1
        if key is None:
            key = lambda x: data[mid]
        while l <= r:
            mid = (l + r) // 2
            if key(mid) >= val:
                r = mid - 1
            else:
                l = mid + 1
        return l

class Solution:
    def shortestSubarray(self, nums: List[int], k: int) -> int:
        ans = float('inf')
        pre = [0]
        for v in nums:
            pre.append(pre[-1] + v)
        # print(pre)
        q = []
        # 单调递增栈, 栈上二分
        for i, v in enumerate(pre):
            while q and pre[q[-1]] >= v:
                q.pop()
            q.append(i)
            t = BinarySearch.bisect_left(q, True, key=lambda x: v - pre[q[x]] < k)
            if t - 1 >= 0:
                ans = min(ans, i - q[t - 1])
        return ans if ans != float('inf') else -1

Search

    Table of Contents