返回

用你的语言:揭开滑动窗口最大值的奥秘

前端

在计算机编程中,滑动窗口是一种技术,它允许我们以固定大小的窗口遍历数据序列。想象一下你在一个有窗户的火车上,而火车正在穿过一个风景如画的乡村。窗户的大小代表了你一次可以看到的风景量,而火车的移动代表了你的窗口在数据序列中的滑动。

滑动窗口最大值 问题要求我们找到一个给定数组中滑动窗口的最大值。我们不关心窗口中的其他值,只关心窗口中最大的那个。

我们从一个简单的例子入手来理解这个概念。考虑数组 [1, 3, -1, -3, 5, 3, 6, 7] 和窗口大小 k = 3。当窗口从左向右滑动时,它依次包含以下元素:

  • [1, 3, -1]:最大值为 3
  • [3, -1, -3]:最大值为 3
  • [-1, -3, 5]:最大值为 5
  • [-3, 5, 3]:最大值为 5
  • [5, 3, 6]:最大值为 6
  • [3, 6, 7]:最大值为 7

如你所见,窗口中的最大值会随着窗口的滑动而变化。我们的目标是找到窗口中所有可能的最大值。

为了解决这个问题,我们可以使用多种算法。一种常见的算法是双端队列 (deque),它是一种可以在两端添加和删除元素的数据结构。

双端队列算法的工作原理如下:

  1. 初始化一个双端队列,从左到右扫描数组。
  2. 对于每个元素,如果它大于双端队列中的最后一个元素,则将双端队列中的所有较小元素弹出,并将新元素添加到双端队列中。
  3. 如果窗口已达到大小 k,则弹出双端队列中的第一个元素,因为该元素已不在窗口中。
  4. 将双端队列中的第一个元素作为窗口中的最大值。

让我们用上面的示例来演示双端队列算法:

  • 扫描到元素 1 时,双端队列为空,所以我们将 1 添加到双端队列中。
  • 扫描到元素 3 时,3 > 1,所以我们将 1 从双端队列中弹出,并添加 3。
  • 扫描到元素 -1 时,-1 < 3,所以我们保留双端队列不变。
  • 扫描到元素 -3 时,-3 < 3,所以我们保留双端队列不变。
  • 扫描到元素 5 时,5 > -3,所以我们将 -3 从双端队列中弹出,并添加 5。
  • 窗口大小现在为 k = 3,所以我们将 1 从双端队列中弹出,因为 1 已不在窗口中。
  • 窗口中的最大值为双端队列中的第一个元素,即 5。

以此类推,我们可以继续扫描数组并找到窗口中的所有最大值。

代码实现

这里有一个用 Python 实现的双端队列算法的示例:

from collections import deque

def max_sliding_window(nums, k):
  """
  Finds the maximum value in a sliding window of size k.

  Args:
    nums: A list of integers.
    k: The size of the sliding window.

  Returns:
    A list of the maximum values in the sliding window.
  """

  # Initialize a deque
  window = deque()

  # Initialize the result list
  result = []

  # Iterate over the nums
  for i in range(len(nums)):
    # If the window is full, remove the first element
    if len(window) == k:
      window.popleft()

    # Remove all smaller elements from the window
    while window and nums[i] > window[-1]:
      window.pop()

    # Add the current element to the window
    window.append(nums[i])

    # If the window is full, add the maximum value to the result list
    if len(window) == k:
      result.append(window[0])

  return result

我希望这个详细的解释和代码示例能够帮助你理解滑动窗口最大值问题及其解决方案。如果你还有任何疑问,请随时提出。