堆的相关题目—滑动窗口

Posted rnanprince

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了堆的相关题目—滑动窗口相关的知识,希望对你有一定的参考价值。

1、数据流滑动窗口平均值

描述

给出一串整数流和窗口大小,计算滑动窗口中所有整数的平均值。

样例

样例1 :

MovingAverage m = new MovingAverage(3);
m.next(1) = 1 // 返回 1.00000
m.next(10) = (1 + 10) / 2 // 返回 5.50000
m.next(3) = (1 + 10 + 3) / 3 // 返回 4.66667
m.next(5) = (10 + 3 + 5) / 3 // 返回 6.00000
来源:https://www.lintcode.com/problem/moving-average-from-data-stream/description
from collections import deque
class MovingAverage:
    def __init__(self, size):
        self.queue = deque()
        self.size = size
        self.sum = 0.0
        
    def next(self, val):
        if  self.size == len( self.queue):
            temp = self.queue.popleft()
            self.sum -= temp
        self.queue.append(val)
        self.sum += val
        
        return self.sum/len(self.queue)

2、数据流的中位数

中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。

例如,

[2,3,4] 的中位数是 3

[2,3] 的中位数是 (2 + 3) / 2 = 2.5

设计一个支持以下两种操作的数据结构:

void addNum(int num) - 从数据流中添加一个整数到数据结构中。
double findMedian() - 返回目前所有元素的中位数。
示例:

addNum(1)
addNum(2)
findMedian() -> 1.5
addNum(3)
findMedian() -> 2

链接:https://leetcode-cn.com/problems/find-median-from-data-stream/submissions/

import heapq
class MedianFinder(object):

    def __init__(self):
        """
        initialize your data structure here.
        """
        self.minheap = []
        self.maxheap = [] 
        self.median = 0.0

    def addNum(self, num):
        """
        :type num: int
        :rtype: None
        """
       
        if len(self.maxheap) <= len(self.minheap):
            heapq.heappush(self.maxheap, -num)
        else:
            heapq.heappush(self.minheap, num)
            
        if len(self.minheap) == 0 or len(self.maxheap) ==0:
            # print(num, self.maxheap, self.minheap)
            return

        if -self.maxheap[0] > self.minheap[0]:
            heapq.heappush(self.maxheap, -heapq.heappop(self.minheap))
            heapq.heappush(self.minheap, -heapq.heappop(self.maxheap))
        # print(num, self.maxheap, self.minheap)        

    def findMedian(self):
        """
        :rtype: float
        """
        if len(self.maxheap) > len(self.minheap):
            return -self.maxheap[0]
        elif len(self.maxheap) < len(self.minheap):
            return self.minheap[0]
        else:
            return float(self.minheap[0] - self.maxheap[0])/2

3、滑动窗口最大值

给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 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

链接:https://leetcode-cn.com/problems/sliding-window-maximum/

class Solution(object):
    def maxSlidingWindow(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        # 单调双边队列
        if not nums or not k :
            return []
        
        def push(queue, nums, i):
            while queue and nums[i] > nums[queue[-1]]:
                queue.pop()
            queue.append(i)
            
        from collections import deque
        res = []
        queue = deque()
        for i in range(k-1):
            push(queue, nums, i)
        
        for i in range(k-1, len(nums)):
            push(queue, nums, i)
            res.append(nums[queue[0]])
            if k == i-queue[0]+1:
                queue.popleft()
        
        return res

4、滑动窗口中位数

https://www.jiuzhang.com/solution/sliding-window-median/#tag-highlight-lang-python(比较难)

5、滑动窗口矩阵的最大值

题目描述
给一个 n * m 的一个矩阵, 以及一个移动的矩阵窗口 (大小为 k * k), 移动窗口从左上角到右下角, 找到每一次移动窗口得到的和中的最大值, 返回 0, 如果结果不存在

来自:https://www.jiuzhang.com/solution/sliding-window-matrix-maximum/#tag-highlight-lang-python

思路:前缀和

题解:

  • sum[i][j]存储左上角坐标为(0,0),右下角坐标为(i,j)的子矩阵的和。
  • sum[i][j] = matrix[i - 1][j - 1] + sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1]递推求值即可,两部分相加,减去重复计算部分。
  • value = sum[i][j] - sum[i - k][j] - sum[i][j - k] + sum[i - k][j - k]可求得一个k * k大小子矩阵的和

6、数据流中第一个唯一的数字

描述

给一个连续的数据流,写一个函数返回终止数字到达时的第一个唯一数字(包括终止数字),如果找不到这个终止数字, 返回 -1.

样例1

输入: 
[1, 2, 2, 1, 3, 4, 4, 5, 6]
5
输出: 3

样例2

输入:
[1, 2, 2, 1, 3, 4, 4, 5, 6]
7
输出: -1

样例3

输入:
[1, 2, 2, 1, 3, 4]
3
输出: 3

来自:https://www.lintcode.com/problem/first-unique-number-in-data-stream/description

知识:python中for......else......的使用

当迭代对象完成所有迭代后且此时的迭代对象为空时,如果存在else子句则执行else子句,没有则继续执行后续代码;如果迭代对象因为某种原因(如带有break关键字)提前退出迭代,则else子句不会被执行,程序将会直接跳过else子句继续执行后续代码

class Solution:
    """
    @param nums: a continuous stream of numbers
    @param number: a number
    @return: returns the first unique number
    """
    def firstUniqueNumber(self, nums, number):
        # Write your code here
        maps = {}
        for i in nums:
            maps[i] = maps.get(i, 0) + 1
            if i == number:
                break
        else:
            return -1
            
        for i in nums:
            if maps[i] == 1:
                return i
            if i == number:
                break

        return -1

  

 

以上是关于堆的相关题目—滑动窗口的主要内容,如果未能解决你的问题,请参考以下文章

滑动窗口相关题目(java版和js版)

滑动 ViewPager 时如何清除片段相关状态

不够细心的失分--滑动窗口

Java 求解滑动窗口最大值

字符串类题目——滑动窗口和递归分治以及一些些位运算的结合

LeetCode(算法)- 239. 滑动窗口最大值