当前位置: 面试刷题>> 滑动窗口(经典算法150题)


题目描述补充

题目:滑动窗口最大值

给定一个数组 nums 和一个滑动窗口的大小 k,请找出该数组的滑动窗口中的最大值。滑动窗口从数组的最左边开始,每次向右移动一个位置,直到无法再移动为止。

示例 1:

输入: nums = [1,3,-1,-3,5,3,6,7], k = 3
输出: [3,3,5,5,6,7]
解释: 
滑动窗口的位置                最大值
---------------               -----
[1  3  -1] -3  5  3  6  7       3
 1 [3  -1  -3] 5  3  6  7       3
 1  3 [-1  -3  5] 3  6  7       5
 1  3  -1 [-3  5  3] 6  7       5
 1  3  -1  -3 [5  3  6] 7       6
 1  3  -1  -3  5 [3  6  7]      7

要求

  • 你可以使用双端队列(deque)来解决这个问题,以便在 O(1) 时间复杂度内完成插入、删除和获取最大值的操作。
  • 请使用 PHP、Python、JavaScript 编写你的解决方案。

示例代码

PHP 示例

function maxSlidingWindow($nums, $k) {
    $deque = new SplDoublyLinkedList(); // 使用 PHP 的双向链表模拟双端队列
    $result = [];
    
    for ($i = 0; $i < count($nums); $i++) {
        // 移除窗口之外的元素
        if (!$deque->isEmpty() && $deque->bottom() < $i - $k + 1) {
            $deque->shift();
        }
        
        // 移除比当前元素小的元素,保证队列头部是最大值
        while (!$deque->isEmpty() && $nums[$deque->top()] < $nums[$i]) {
            $deque->pop();
        }
        
        $deque->push($i); // 插入当前元素的索引
        
        // 当窗口形成后,开始记录结果
        if ($i >= $k - 1) {
            $result[] = $nums[$deque->bottom()];
        }
    }
    
    return $result;
}

注意: PHP 标准库中没有直接的双端队列实现,这里使用 SplDoublyLinkedList 作为替代,并手动管理头部和尾部的操作。

Python 示例

from collections import deque

def maxSlidingWindow(nums, k):
    deque = deque()
    result = []
    
    for i in range(len(nums)):
        # 移除窗口之外的元素
        if deque and deque[0] == i - k:
            deque.popleft()
        
        # 移除比当前元素小的元素,保证队列头部是最大值
        while deque and nums[deque[-1]] < nums[i]:
            deque.pop()
        
        deque.append(i) # 插入当前元素的索引
        
        # 当窗口形成后,开始记录结果
        if i >= k - 1:
            result.append(nums[deque[0]])
    
    return result

JavaScript 示例

function maxSlidingWindow(nums, k) {
    const deque = [];
    const result = [];
    
    for (let i = 0; i < nums.length; i++) {
        // 移除窗口之外的元素
        if (deque.length > 0 && deque[0] === i - k) {
            deque.shift();
        }
        
        // 移除比当前元素小的元素,保证队列头部是最大值
        while (deque.length > 0 && nums[deque[deque.length - 1]] < nums[i]) {
            deque.pop();
        }
        
        deque.push(i); // 插入当前元素的索引
        
        // 当窗口形成后,开始记录结果
        if (i >= k - 1) {
            result.push(nums[deque[0]]);
        }
    }
    
    return result;
}

以上代码均实现了滑动窗口的最大值查找,通过双端队列(deque)在 O(1) 时间复杂度内完成窗口内最大值的更新。

推荐面试题