剑指offer(59):滑动窗口的最大值(python版)

编程题 专栏收录该内容
4 篇文章 0 订阅

本博客主要内容为图书《剑指offer》第二版47 题的解题思路及代码。方法可能还有不足之处,欢迎大家讨论评论。

1. 题目描述

  给定一个数组和一个滑动窗口的大小,请找出所有滑动窗口里的最大值。例如,如果输入数组 {2,3,4,6,2,5,1} 及滑动窗口的大小 3,那么一定存在 5 个滑动窗口,它们的最大值分别为 {4,6,6,6,5}。

2. 题目分析

  在书上的方法比较好,但是如果不是很理解这个过程的话,不是很好理解书上所讲述内容的含义,在这里我用一种比较容易理解的方式进行描述。为了输出每个窗口中的最大值,我们使用了一个数组temp,数组temp中存放着当前窗口的最大值,和按需排列好的次大值,并且这些次大值在数组中的位置只能是位于最大之后的,数组 temp 的最大规模为 size -1。

  以上面的题目为例,首先在数组temp中存储 2 为目前的最大值,之后读取原始数组中的数字 3 ,由于3 比 2 大,所以将 2 弹出,将 3 压入;然后读取原始数组中的数字 4,由于4 比 3 大,所以将 3 弹出,将 4 压入;读取原始数组中的数字 6,由于 6 比 4 大,所以将 4 弹出,将 6 压入;读取原始数组中的数字 2,由于 6 比 2 大,所以 6 不会被弹出,但是这个时候 temp 的大小小于 size - 1,所以将 2 压入(因为他是目前除了6 以外最大的元素);读取原始数组中的数字 5,由于 5 比 2 大,所以将 2 弹出,先不压入5,而是将 5 与 6 进行比较,由于 6 比 5 大,所以 6 不会被弹出,但是这个时候 temp 的大小小于 size - 1,所以将 5 压入;在读取原始数组中的数字 1 之前我们发现,如果滑动窗口移动到了包含 1 的位置,那么这个时候 6 已经是在窗口之外了,也就是说 6 是过期的,所以这个时候应该首先将 6 弹出,此时 temp 只剩下 5 ,取原始数组中的数字 1,由于 5 比 1 大,所以 5 不会被弹出,但是这个时候 temp 的大小小于 size - 1,所以将 1 压入。

  经过上面的举例分析,我们已经得到在滑动窗口滑动的过程中 temp 的取值过程。但是并不是在读取第一个元素的时候就开始输出滑动窗口中的最大值,而是当整个滑动窗口都读取到的时候才输出

  所以找出滑动窗口的最大值的过程,实际上就两步工作:

  (1)判断当前的最大值是否过期。

  (2)将读入的数字与 temp 中的元素从后向前依次比较大小,将 temp 中小于读入数字的元素都弹出;如果删除后 temp 的大小还没有达到 size - 1,那么将这个元素压入(删除后 temp 的大小有可能达到 size - 1 嘛?有可能的!因为可能经过比较发现 temp 中没有元素被弹出)。

3. 代码实现

# -*- coding:utf-8 -*-
class Solution:
    def maxInWindows(self, num, size):
        # 如果数组 num 不存在,则返回 []
        if not num:
            return []
        # 如果滑动窗口的大小大于数组的大小,或者 size 小于 0,则返回 []
        if size > len(num) or size <1:
            return []
        
        # 如果滑动窗口的大小为 1 ,则直接返回原始数组
        if size == 1:
            return num
        
        # 存放最大值,次大值的数组,和存放输出结果数组的初始化
        temp = [0]
        res = []
        
        # 对于数组中每一个元素进行判断
        for i in range(len(num)):
            # 判断第 i 个元素是否可以加入 temp 中
            # 如果比当前最大的元素还要大,清空 temp 并把该元素放入数组
            # 首先判断当前最大的元素是否过期
            if i -temp[0] > size-1:
                temp.pop(0)
            # 将第 i 个元素与 temp 中的值比较,将小于 i 的值都弹出
            while (len(temp)>0 and num[i] >= num[temp [-1]]):
                temp.pop()
            # 如果现在 temp 的长度还没有达到最大规模,将元素 i 压入
            if len(temp)< size-1:
                temp.append(i)
            # 只有经过一个完整的窗口才保存当前的最大值
            if i >=size-1:
                res.append(num[temp [0]])
        return res
  • 5
    点赞
  • 6
    评论
  • 6
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值