📌  相关文章
📜  所有可能长度的每个子数组中存在的最小元素(1)

📅  最后修改于: 2023-12-03 15:39:40.060000             🧑  作者: Mango

所有可能长度的每个子数组中存在的最小元素

问题介绍

给定一个含有 n 个元素的整型数组 nums,对于所有长度为 k 的子数组,找到其中最小的元素,并将其保存在一个长度为 n-k+1 的数组 output 中。例如,对于数组 nums = [3, 1, 5, 7, 2] 和 k = 3,我们有 output = [1, 1, 2]。

这个问题可以通过暴力枚举子数组,找到其中的最小值并保存。但是该方法的时间复杂度为 $O(nk)$, 不够高效。 下面将会介绍一种时间复杂度为 $O(n)$ 的解法。

解法

维护一个单调非增的队列。对于当前位置 i,如果 nums[i] 大于队尾元素,则将队尾元素出队,直到队列为空或者队尾元素大于等于 nums[i]。

由于队列中的元素始终保持单调不升的顺序,并且每个元素只会进队一次,出队一次,因此队列中最多只有 n 个元素。因此算法的时间复杂度为 $O(n)$。

下面是用 Python 语言实现的代码片段:

def min_subarray(nums: List[int], k: int) -> List[int]:
    n = len(nums)
    ans = []
    q = []

    for i in range(n):
        # 维护队列单调不升
        while q and nums[i] < nums[q[-1]]:
            q.pop()

        q.append(i)

        # 队头元素过期
        if q[0] == i - k:
            q.pop(0)

        # 输出答案
        if i >= k - 1:
            ans.append(nums[q[0]])

    return ans
总结

该算法的核心在于使用单调队列来维护所有可能长度的子数组中存在的最小元素。通过保证队列单调不升性,可以在 $O(n)$ 的时间复杂度内找到每个子数组中的最小值。