返回
递增队列问题 - LeetCode 862. Shortest Subarray with Sum at Least K 题解
闲谈
2023-11-02 07:00:05
我们都有一个共同的目标,就是要解决一个具有挑战性的问题:在给定的数组中找到满足总和小于 K 的最短子数组。当你想说,这是一件容易的事,就记住,它被标记为一个中等难度的问题。不过,别担心,因为它根本不是一个难题。
考虑一个更简单的例子,一个由 7 个整数构成的数组:[1, 2, 3, 4, 5, 6, 7],设定的目标总和为 15。这个数组中的子数组有许多种,为了节省时间,我假设只有两个最短的满足条件:
[1, 2, 3, 4, 5](和为 15)
[2, 3, 4, 5, 6](和为 20)
现在,我们对问题本身进行更好的概括。给定一个数组 nums 和一个整数 k,我们需要找到最短的连续子数组,其元素之和等于或大于 k。当数组为空时,我们返回 0。这是一个经典的滑动窗口问题。
解决这个问题的一个更优的方法是使用递增队列。简单地说,递增队列是一个 FIFO(先进先出)的数据结构,其中元素按非递减顺序排序。这意味着队列中的第一个元素始终是最小的。
为了更好地理解它的工作原理,让我们看看它是如何解决这个问题的:
1. 我们将递增队列初始化为空。
2. 我们从数组开头开始,并遍历整个数组。
3. 对于数组中的每个元素,我们检查队列是否为空。如果是,我们直接将元素放入队列中。如果不是,我们比较当前元素和队列末尾的元素。
4. 如果当前元素大于或等于队列末尾的元素,我们将队列末尾的元素出队,然后将当前元素入队。
5. 我们继续比较当前元素和队列末尾的元素,直到它们相等或当前元素小于队列末尾的元素。
6. 一旦我们找到一个元素使队列末尾的元素大于或等于当前元素,我们计算从队列开头到当前元素的总和。如果总和大于或等于 k,我们更新最小长度并记录子数组的起始和结束索引。
7. 我们从队列中移除第一个元素并重复从第 3 步开始,直到我们到达数组末尾。
现在,让我们用代码来实现这个算法。我们使用 Python 语言编写代码,以便您能够轻松地理解和运行它。
def shortest_subarray(nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: int
"""
# 初始化递增队列和最短长度
queue = []
min_len = float('inf')
# 从数组开头开始,遍历整个数组
for i, num in enumerate(nums):
# 将元素放入队列
while queue and queue[-1] > num:
queue.pop()
queue.append(num)
# 计算总和并更新最短长度
total = 0
for j in range(len(queue)):
total += queue[j]
if total >= k:
min_len = min(min_len, i - j + 1)
break
# 如果没有找到满足条件的子数组,返回 0
return min_len if min_len != float('inf') else 0
# 测试代码
nums = [1, 2, 3, 4, 5, 6, 7]
k = 15
result = shortest_subarray(nums, k)
print(result) # 输出:5
希望这份题解能够帮助你理解这个算法并解决这个问题。如果你有任何问题或建议,请随时在评论区留言。