Python之队列和堆

本文回顾了哈希表和链表的基础知识,接着深入探讨了队列的概念和在LeetCode中的应用,包括如何实现滑动窗口最大值。最后,详细介绍了堆的定义、Python中的堆操作及在LeetCode题目中的实践。通过本文,读者可以更好地理解和运用这些数据结构。

一、复习

1.1、哈希表

总结:

在上次练习中,最大的感受是方便快捷。

把数据存储到哈希表中,可以快速查找重复的,也可以直接取出想要的数据,时间复杂度低,以空间换时间

1.2、链表

总结:

链表灵活性很强,可以双向,也可以循环,最重要的是可以灵活删除添加元素

不过缺点也很明显,想要查找重复或者取出想要的数据比较麻烦

二、队列

2.2、定义

  • 队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。

  • 队列的数据元素又称为队列元素。在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出(FIFO—first in first out)线性表。

在这里插入图片描述

2.2、leetcode应用

    1. Sliding Window Maximum
  1. 方法一、
class Solution(object):
    def maxSlidingWindow(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        
        win = []
        n = len(nums)
        
        if nums != []:
            for i in range(n-k+1):
                win.append(max(nums[i:i+k]))   # 等同于滑动队列,先进先出
        
        return win
  • 结果
    在这里插入图片描述
  1. 方法二
class Solution(object):
    def maxSlidingWindow(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        import heapq

        win = []
        hea = []   
        # 用hea实现单向队列操作,注意的是,千万不能:win = hea = [],这样会导致错误的
        
        n = len(nums)
        
        hea.append(0)

        for num in nums[0:k-1]:
            hea.append(num)

        if nums != []:
            for i in range(k - 1, n):
                hea.append(nums[i])
                hea.pop(0)
                win.append(max(hea))

        return win
  • 结果

在这里插入图片描述

  1. 方法三
class Solution(object):
    def maxSlidingWindow(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        win = []
        hea = []

        n = len(nums)

        for i in range(k - 1):  # 先建立第一个窗口的前k-1个
            while hea != [] and nums[hea[-1]] < nums[i]:  # 一直比较新数及队尾元素,若队尾较小则出队
                hea.pop()
            hea.append(i)  #新数的索引入队

        if nums != []:
            for i in range(k - 1, n):
                if hea != [] and (i - hea[0]) == k:  # 队列中最大值的索引与新数的索引如果溢出窗口k,则队头出队
                    hea.pop(0)
                while hea != [] and nums[hea[-1]] < nums[i]:  
                    hea.pop()
                hea.append(i)
                win.append(nums[hea[0]])    # 队头的索引指示该窗口下的最大值

        return win
  • 结果
    在这里插入图片描述

三、堆

3.1、定义

  • 堆(英语:heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质:
    1. 堆中某个节点的值总是不大于或不小于其父节点的值;
    2. 堆总是一棵完全二叉树。
    3. 将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。
    4. 常见的堆有二叉堆、斐波那契堆等。常见的堆有二叉堆、斐波那契堆等。
    5. 堆是线性数据结构,相当于一维数组,有唯一后继。堆是线性数据结构,相当于一维数组,有唯一后继。
    6. 堆的定义如下:n个元素的序列{k1,k2,ki,…,kn}当且仅当满足下关系时,称之为堆。
    7. (ki <= k2i,ki <= k2i+1)或者(ki >= k2i,ki >= k2i+1), (i = 1,2,3,4…n/2)
    8. 若将和此次序列对应的一维数组(即以一维数组作此序列的存储结构)看成是一个完全二叉树,则堆的含义表明,完全二叉树中所有非终端结点的值均不大于(或不小于)其左、右孩子结点的值。由此,若序列{k1,k2,…,kn}是堆,则堆顶元素(或完全二叉树的根)必为序列中n个元素的最小值(或最大值)。

3.2、Python中常用用法

import heapq

heap = []#建立一个常见的堆

heappush(heap,item)#往堆中插入一条新的值

item = heappop(heap)#弹出最小的值

item = heap[0]#查看堆中最小的值,不弹出

heapify(x)#以线性时间将一个列表转为堆

item = heapreplace(heap,item)#弹出一个最小的值,然后将item插入到堆当中。堆的整体的结构不会发生改变。
heappoppush()#弹出最小的值,并且将新的值插入其中

merge()#将多个堆进行合并

nlargest(n , iterbale, key=None)从堆中找出做大的N个数,key的作用和sorted( )方法里面的key类似,用列表元素的某个属性和函数作为关键字

3.3、leetcode应用

class Solution(object):
    def maxSlidingWindow(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        import heapq   # 需要这个模块建立堆

        win = []
        hea = []

        n = len(nums)

        for i in range(n):
            while hea != [] and (i - hea[0][1]) > k - 1:  # 如果堆顶点对应的索引溢出,删除堆顶点(即删除最大值)
                heapq.heappop(hea)
            heapq.heappush(hea, (-nums[i], i))  #同时将数值和索引输入堆,以便判断堆顶点的索引是否溢出
            if i > k - 2:  # 在堆至少为窗口大小时,才开始输出最大值
                win.append(-hea[0][0])

        return win
  • 结果

在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值