代码随想录刷题营Day13(150:逆波兰表达式求值,239:滑动窗口的最大值,347:前K个高频元素)

150:逆波兰表达式求值

这个题是典型的用栈来去辅助求解的题目,很经典。本来我以为要构造两个栈,一个符号栈一个存储操作数的栈,但后来想想,构造一个存储操作数的栈就好了,符合直接拿出来就用了,还给他建个栈干嘛。。。整体思路就是,先遍历字符串,如果是遇到操作数,就直接进栈,如果是遇到符号,就取操作数栈中的前两个,做计算即可。但是这里要注意的是,是取出来的第一个数(操作符)第二个数,还是第二个数(操作符)第一个数。这个很重要,因为我写代码时候写的是第一个数(操作符)第二个数,所以就没通过,改完就好了。
具体代码如下:

    def evalRPN(self,tokens):
        stack=[]
        for i in range(len(tokens)):
            if tokens[i]=="+" or tokens[i]=="-" or tokens[i]=="*" or tokens[i]=="/":
                num1=int(stack.pop())
                num2=int(stack.pop())
                if tokens[i]=="+":
                    num=num2+num1
                elif tokens[i]=="-":
                    num=num2-num1
                elif tokens[i]=="*":
                    num=num2*num1
                elif tokens[i]=="/":
                    num=int(num2/num1)
                stack.append(num)
            else:
                stack.append(int(tokens[i]))
        return stack.pop()

347:前K个高频元素:

这个题看完就知道是map!用map去做统计,然后按照value排序取前K个高频的。思路很简单,但是为了降低一点复杂度,从快排的nlogn到nlogK,那还是得用堆排序来辅助求解,我们只需要维护前K个高频的就好了。这个题,主要是带我开辟了“heapq”的这片乐土,构造小顶堆的神器!如果碰到优先队列的题,就需要考虑用它了,本题的具体代码如下:

    def topKFrequent(self,nums,k):
        store=dict()
        for i in range(len(nums)):
            if nums[i] in store:
                store[nums[i]]=store[nums[i]]+1
            else:
                store[nums[i]]=1
        pri_que=[]
        for key,value in store.items():
            heapq.heappush(pri_que,(value,key))
            if len(pri_que)>k:
                heapq.heappop(pri_que)
        result=[0]*k
        for i in range(k-1,-1,-1):
            result[i]=heapq.heappop(pri_que)[1]
        return result

好吧,那就巩固一下使用优先队列,python的工具“heapq”的语法吧!
(1)简介:heapq 库是Python标准库之一,提供了构建小顶堆的方法和一些对小顶堆的基本操作方法(如入堆,出堆等),可以用于实现堆排序算法。
(2)使用heapq来创建堆。

# coding=utf-8
import heapq
array = [10, 17, 50, 7, 30, 24, 27, 45, 15, 5, 36, 21]
heap = []
for num in array:
    heapq.heappush(heap, num)
print("array:", array)
print("heap: ", heap)
 
heapq.heapify(array)
print("array:", array)

可以看到,heapq中创建堆的方法有两种。
heappush(heap, num),先创建一个空堆,然后将数据一个一个地添加到堆中。每添加一个数据后,heap都满足小顶堆的特性。
heapify(array),直接将数据列表调整成一个小顶堆(调整的原理参考上面堆排序的文章,heapq库已经实现了)。
结果:

array: [10, 17, 50, 7, 30, 24, 27, 45, 15, 5, 36, 21]
heap:  [5, 7, 21, 15, 10, 24, 27, 45, 17, 30, 36, 50]
array: [5, 7, 21, 10, 17, 24, 27, 45, 15, 30, 36, 50]

(3)使用heapq实现堆排序。

array = [10, 17, 50, 7, 30, 24, 27, 45, 15, 5, 36, 21]
heap = []
for num in array:
    heapq.heappush(heap, num)
print(heap[0])
# print(heapq.heappop(heap))
heap_sort = [heapq.heappop(heap) for _ in range(len(heap))]
print("heap sort result: ", heap_sort)

先将待排序列表中的数据添加到堆中,构造一个小顶堆,打印第一个数据,可以确认它是最小值。然后依次将堆顶的值取出,添加到一个新的列表中,直到堆中的数据取完,新列表就是排序后的列表。
heappop(heap),将堆顶的数据出堆,并将堆中剩余的数据构造成新的小顶堆。
结果:

5
heap sort result:  [5, 7, 10, 15, 17, 21, 24, 27, 30, 36, 45, 50]

(4)获取堆中的最小值或最大值

array = [10, 17, 50, 7, 30, 24, 27, 45, 15, 5, 36, 21]
heapq.heapify(array)
print(heapq.nlargest(2, array))
print(heapq.nsmallest(3, array))

结果:
[50, 45]
[5, 7, 10]
nlargest(num, heap),从堆中取出num个数据,从最大的数据开始取,返回结果是一个列表(即使只取一个数据)。如果num大于等于堆中的数据数量,则从大到小取出堆中的所有数据,不会报错,相当于实现了降序排序。参考链接:Python heapq库的用法介绍


239:滑动窗口的最大值:

刷这道题是真不容易:
在这里插入图片描述
提交了好多次才通过:
不过时间用的比较长,那也不管了,起码做对了,吼吼!
在这里插入图片描述
这个题,看完视频后就自己摸索着写,觉得自己get到精髓了,但就是写不对,问题在哪里呢,主要是,需要判断,每进一个元素,需要将前面的元素(哪怕他是最大的)也要弹出,而且还需要保留次大值,以至于最大值因为k窗口大小的问题,弹出之后,次大值还能再补上!这一点,写了好久,从下午写道晚上,哎,觉得自己有点笨了。
具体代码如下:

    def maxSlidingWindow(self,nums,k):
        d=deque()
        res=[]
        max=-10000000
        for i in range(k):
            if i==0:
                d.append(nums[i])
            else:
                while d and nums[i]>d[-1]:
                    d.pop()
                d.append(nums[i])
        res.append(d[0])
        for i in range(k,len(nums)):
            if d and nums[i-k]==d[0]:
                d.popleft()
            while d and nums[i]>d[-1]:
                d.pop()
            d.append(nums[i])
            res.append(d[0])
        return res

首先分为两个阶段进行求解res,第一个阶段是k以内的,再一个阶段是大于k的。还要注意是弹出左边的还是弹出右边的,左边的就是队头,右边的是队尾。通过维护一个自定义的单调队列来实现滑动窗口的效果,注意i-k的理解,i-k的意思是,检测队头的值是否等于“窗口外的第一个值(最接近窗口边缘的)”,就要删掉。这一点,很重要!
虽然这一个题是二刷了,但是做的还是这么磕磕绊绊,不过,我记得关于这个题的非常有趣的评论,哈哈!这瞬间让算法题目变得可爱起来啦!
在这里插入图片描述


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值