zoukankan      html  css  js  c++  java
  • 【队列-01】队列题目解析

    目录

    1. 面试题59 - I. 滑动窗口的最大值/239. 滑动窗口最大值
    2. 面试题59 - II. 队列的最大值
    3. 剑指 Offer 13. 机器人的运动范围

       

    队列:普通队列满足,先进先出,目前也支持双端出的队列形式。

       

    一、面试题59 - I. 滑动窗口的最大值/239. 滑动窗口最大值

    1.1 问题

    给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的个数字。滑动窗口每次只向右移动一位。返回滑动窗口中的最大值。

    进阶:你能在线性时间复杂度内解决此题吗?

    示例:

    输入: 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

    提示:

    1 <= nums.length <= 10^5

    -10^4 <= nums[i] <= 10^4

    1 <= k <= nums.length

    1.2 解析

    利用双向队列,按照递减的排序来做,滑动的过程中可能会剔除一些没有可能的小数字

    1.3 代码

    class Solution:

        def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:

            if not nums or k == 0return []

            deque = collections.deque()   #定义双向队列,两边都可以进出

            for i in range(k): 未形成窗口

                while deque and deque[-1] < nums[i]: #保持deque是一个递减的数组

                    deque.pop()

                deque.append(nums[i])  #根据上面的调整,插入新来的数,也能保持递减

            res = [deque[0]]  #将最前面的数插入加过中,因为此时就是最大的

            for i in range(k, len(nums)): 形成窗口后

                if deque[0] == nums[i - k]: #如果最大值落在滑动窗口的左侧,要将其删除

                    deque.popleft()

                while deque and deque[-1] < nums[i]: #保持deque是一个递减的数组

                    deque.pop()

                deque.append(nums[i])

                res.append(deque[0])

            return res

    二、面试题59 - II. 队列的最大值

    2.1 问题

    请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_valuepush_back pop_front 的均摊时间复杂度都是O(1)。若队列为空,pop_front max_value 需要返回 -1

    示例 1

    输入:

    ["MaxQueue","push_back","push_back","max_value","pop_front","max_value"]

    [[],[1],[2],[],[],[]]

    输出: [null,null,null,2,1,2]

    示例 2

    输入:

    ["MaxQueue","pop_front","max_value"]

    [[],[],[]]

    输出: [null,-1,-1]

    2.2 代码

    import queue

    class MaxQueue:

        """1队列+1数组"""

        def __init__(self):

            self.queue = queue.Queue()

            self.stack = []      #  用于存放最大值的数组

        def max_value(self) -> int:

            return self.stack[0if self.stack else -1

        def push_back(self, value: int) -> None:

            self.queue.put(value)     

            while self.stack and self.stack[-1] < value: #保持stack是递减的形式,并且该数值之前,都最大

                self.stack.pop()

            self.stack.append(value)

        def pop_front(self) -> int:

            if not self.stack: return -1 # stack为空,即对应的queue也为空了

            ans = self.queue.get()

            if ans == self.stack[0]:

                self.stack.pop(0)

            return ans

    三、剑指 Offer 13. 机器人的运动范围

    3.1 问题

    地上有一个mn列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?

       

    示例 1

    输入:m = 2, n = 3, k = 1

    输出:3

    示例 2

    输入:m = 3, n = 1, k = 0

    输出:1

    3.2 代码

    class Solution:

       

        def sum_rc(self,row,col):

            tmp = 0

            while row > 0:

                tmp += row % 10

                row //=  10

            while col > 0 :

                tmp += col % 10

                col //= 10

            return tmp

       

        def movingCount(self, m: int, n: int, k: int) -> int:

            marked = set()  将访问过的点添加到集合marked,(0,0)开始

            queue = collections.deque()

            queue.append((0,0))

            while queue:

                x, y = queue.popleft()

                if (x,y) not in marked and self.sum_rc(x,y) <= k:

                    marked.add((x,y)) 

                    for dx, dy in [(1,0),(0,1)]:  仅考虑向右和向下即可,注意在if内部

                        if 0 <= x + dx < m and 0 <= y + dy < n:

                            queue.append((x+dx,y+dy))  #增加两个坐标

            return len(marked)  

       

    参考文献

    1https://leetcode-cn.com/

    2一题的答案动画解析

    3第二题动画解析

  • 相关阅读:
    BestCoder17 1001.Chessboard(hdu 5100) 解题报告
    codeforces 485A.Factory 解题报告
    codeforces 485B Valuable Resources 解题报告
    BestCoder16 1002.Revenge of LIS II(hdu 5087) 解题报告
    codeforces 374A Inna and Pink Pony 解题报告
    codeforces 483B Friends and Presents 解题报告
    BestCoder15 1002.Instruction(hdu 5083) 解题报告
    codeforces 483C.Diverse Permutation 解题报告
    codeforces 483A. Counterexample 解题报告
    NSArray中地内存管理 理解
  • 原文地址:https://www.cnblogs.com/yifanrensheng/p/13771886.html
Copyright © 2011-2022 走看看