牛客——堆/栈/队列

1.用两个栈实现队列

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
栈:先进后出,队列:先进先出

class Solution:
    def __init__(self):
        self.stack1 = []
        self.stack2 = []
    def push(self, node):
        # write code here
        self.stack1.append(node)
        # 插入
    def pop(self):
        # return xx
        if len(self.stack2) == 0:
            while (len(self.stack1) != 0):
                # 把1里边的弹出,依次加入2里边
                self.stack2.append(self.stack1.pop())# .pop 是直接在调用
        value = self.stack2.pop()
        return value

2.包含min函数的栈

在这里插入图片描述
在这里插入图片描述
题都看不懂
在这里插入图片描述

class Solution:
    def __init__(self):
        self.stack=[]
        self.stack_min=[]
        # 这个得看视频 我说不明白 引入了一个辅助栈
    def push(self, node):# 插入
        # write code here
        self.stack.append(node)
        
        if self.stack_min==[]:
            self.stack_min.append(node)
        else:
            val=min(node,self.stack_min[-1])
            self.stack_min.append(val)
    def pop(self):# 弹出
        # write code here
        self.stack.pop()
        self.stack_min.pop()
        
    def top(self):# 栈顶
        # write code here
        return self.stack[-1]
    def min(self):# 最小
        # write code here
        return self.stack_min[-1]

3.有效括号序列

在这里插入图片描述
在这里插入图片描述


一个不正确的方法

class Solution:
    def isValid(self , s: str) -> bool:
        # write code here
        #长度为奇数 一定不对
        if len(s)%2 == 1:
            return False
        #只有3种括号在s中,才进行替换
        while '{}' in s or '[]' in s or '()' in s:
            s = s.replace('[]','').replace('{}','').replace('()','')
        return True if s=='' else False

正确的做法,这个不是顺序做的,而是倒序

class Solution:
    def isValid(self , s: str) -> bool:
        # write code here
        if s == '' or s[-1] == '{' or s[-1] == '[' or s[-1] == '(':
            return False
        stack = []
        for i in reversed(s):
            # reserved() 是 Python 内置函数之一
            # 对于给定的序列(包括列表、元组、字符串以及 range(n) 区间),返回一个逆序序列的迭代器(用于遍历该逆序序列)
            if i == '}' or i == ']' or i == ')':
                stack.append(i)
            else:
                if len(stack) == 0:
                    return False
                if (i == '{' and stack[-1] == '}') or (i == '[' and stack[-1] == ']') or (i == '(' and stack[-1] == ')'):
                    stack.pop(-1)
#         return True if len(stack) == 0 else False
        return len(stack) == 0 

正序

class Solution:
    def isValid(self , s: str) -> bool:
        # write code here
        if s == '' or s[-1] == '{' or s[-1] == '[' or s[-1] == '(':
            return False
        stack = []
        for i in s:
            if i == '{' or i == '[' or i == '(':
                stack.append(i)
            else:
                if len(stack) == 0:
                    return False
                if (i == '}' and stack[-1] == '{') or (i == ']' and stack[-1] == '[') or (i == ')' and stack[-1] == '('):
                    stack.pop(-1)
        return len(stack) == 0 

4.滑动窗口的最大值(数据流)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

# 使用队列
# 数组【2,3,4,2,6,2,5,1】为例,滑动窗口大小为3
# 1、先把第一个数字2加入队列,第二个数字是3,比2大,所以2不可能是最大值,所以把2删除,3存入队列。
# 2、第三个数是4,比3大,同样删3存4,此时滑动窗口以遍历三个数字,最大值4在队列的头部。
# 3、第4个数字是2,比队列中的数字4小,当4滑出去以后,2还是有可能成为最大值的,因此将2加入队列尾部,此时最大值4仍在队列的头部。
# 4、第五个数字是6,队列的数字4和2都比它小,所以删掉4和2,将6存入队列尾部,此时最大值6在队列头部。
# 5、第六个数字是2,此时队列中的数6比2大,所以2以后还有可能是最大值,所以加入队列尾部,此时最大值6在仍然队列头部。
# 依次进行,这样每次的最大值都在队列头部。
# 还有一点需要注意的是:如果后面的数字都比前面的小,那么加入到队列中的数可能超过窗口大小,
# 这时需要判断滑动窗口是否包含队头的这个元素,
# 为了进行这个检查,我们可以在队列中存储数字在数组中的下标,而不是数值,
# 当一个数字的下标和当前出来的数字下标之差大于等于滑动窗口的大小时,这个元素就应该从队列中删除。
class Solution:
    def maxInWindows(self , num: List[int], size: int) -> List[int]:
        # write code here
        queue=[]# 存的是下标
        res=[]# 这个是最后结果
        i=0# i是找的值的左边的下标
        # 整体是属于 不断的加入 不断的弹出这么在搞
        while size>0 and i<len(num):
            if len(queue)>0 and i-size+1>queue[0]:# 存储的下标>0 存储的下标已经不符合要求了 要弹出
                # 每一步都在检验 我现在的下标和存储的下标合不合适
                queue.pop(0)
            while len(queue)>0 and num[queue[-1]]<num[i]:# 当前值比存进去的值大 所以删掉现在这个
                queue.pop()
            queue.append(i)
            # 把符合的下标存入队列
            if i>=size-1:# 把搞定的下标换成数字存入res
            	# 因为每增加一个数就会多一个最大值,所以只要>=size就可以了
                # 需要注意的就是前size个一直不能存
                res.append(num[queue[0]])
            i+=1
        return res

暴力 有一个特别长的肯定是跑不完的

class Solution:
    def maxInWindows(self , num: List[int], size: int) -> List[int]:
        # write code here
        # 暴力 有一个特别长的肯定是跑不完的
        left,n=0,len(num)
        x=[]
        if n==0 or size>n:
            return []
        while left+size<n+1:
            x.append(max(num[left:left+size]))
            left+=1
        return x

5.最小的K个数

在这里插入图片描述
我会用的白痴方法

class Solution:
    def GetLeastNumbers_Solution(self, tinput, k):
        # write code here
        list=[]
        if len(tinput)<k:
            return list
        else:
            tinput.sort()
            return tinput[:k]

在这里插入图片描述
在这里插入图片描述

借助最大最小堆

import heapq
class Solution:
    def GetLeastNumbers_Solution(self , input: List[int], k: int) -> List[int]:
        # write code here
        # 建立新容器 input中的值遍历 比容器最大值小的话 就进行替换
        # 用到了最大堆
        if k==0:
            return []
        # python中只有最小堆 所以就要将所有元素取反 弹出元素的时候也取反
        heap=[-x for x in input[:k]]
        heapq.heapify(heap)# 借助函数将其转换为堆
        for num in input[k:]:
            if -num > heap[0]:
                heapq.heapreplace(heap,-num)# 将heap堆顶的移出 并把-num放进去
        return [-x for x in heap]

6.寻找第K大

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

同样也是借助最大堆
小顶堆+相反数:

import heapq
class Solution:
    def findKth(self , a: List[int], n: int, K: int) -> int:
        # write code here
        heap = []
        for i in range(n):
            heapq.heappush(heap, -a[i]) # 小顶堆存进去负数
        for i in range(K-1):
            heapq.heappop(heap) #出队前K-1个(最大的)
        return -heapq.heappop(heap) # 相反数

快速排序:

class Solution:
    def findKth(self , a: List[int], n: int, K: int) -> int:
         return self.quickSort(a, 0, n-1, K)

    def quickSort(self, a, start, end, k):
        if start>end:
            return -1
        pivot = a[start]
        left,right = start,end
        while left<right: # 和下面的小于号一致
            while left<right and a[right]<=pivot: # 由大到小
                right -= 1
            while left<right and a[left]>=pivot:
                left += 1
            if left!=right:
                a[left],a[right] = a[right],a[left]
        a[left],a[start] = a[start],a[left] # 最后left是比pivot大的
        if left==k-1: # 是序号,第k个
            return a[left]
        elif left<k-1:
            return self.quickSort(a, left+1, end, k)
        else:
            return self.quickSort(a, start, left-1, k)


7.数据流中的中位数

在这里插入图片描述
在这里插入图片描述
这道题为了找数据流的中位数,就建立了两个堆,最大堆和最小堆,不断的将数据加入最大堆,并把最大堆的堆顶弹出压入到最小堆里边,这样他自己就排好序了,这时候两个堆顶就是最大堆的最小值和最小堆的最大值,为了保证两个堆顶内数据个数一样多就需要不断地压入弹出。
最后为了取中位数,我们就直接取两个的堆顶,奇数时就是最小堆堆顶,偶数时就是二者平均值。

import heapq
class Solution:# 排序 借助最大堆最小堆 找左侧最大值 右侧最小值
    # 先插入最小堆 然后弹出最小堆里边最大的 把这个弹出的值插入最大堆
    
    def __init__(self):
        self.maxHeap=[]
        self.minHeap=[]
    def Insert(self, num):
        # 为了使数据平均分到两堆:若两堆元素数目相等 就让min 再+1
        # 具体:1.将新元素加入max 2.将max堆顶加入min
        # write code here
        if len(self.maxHeap)==len(self.minHeap):# 这里就是在min中多加一个
            heapq.heappush(self.minHeap,-heapq.heappushpop(self.maxHeap,-num)) # 因为python里边没有最大堆 所以就取反 然后加入最小堆
        else:# 这里就是两个不相等的时候 在min里边加一个 然后弹出最大的加入到max
            heapq.heappush(self.maxHeap,-heapq.heappushpop(self.minHeap,num))
    def GetMedian(self):
        # write code here
        if len(self.maxHeap)==len(self.minHeap):
            return (self.minHeap[0]-self.maxHeap[0])/2.0
        else:
            return self.minHeap[0]

8.表达式求值(±*/都可以)

在这里插入图片描述
在这里插入图片描述

class Solution:
    def solve(self , s: str) -> int:
        # write code here
        return self.helper(list(s))
 
    def helper(self, list_str):
        stack = []
        num = 0
        sign = "+"
 
        while len(list_str) > 0:
            c = list_str.pop(0)
            if c.isdigit():# 借助一个函数来判断是不是数字
                num = num * 10 + int(c)
            if c == "(":# 遇到括号的时候需要递归着来做一下 这样可以优先级更高
                num = self.helper(list_str)
            if ((not c.isdigit()) and c != " ") or len(list_str) == 0:
                if sign == "+":
                    stack.append(num)
                elif sign == "-":
                    stack.append(-num)
                elif sign == "*":
                    tmp = stack.pop()
                    stack.append(tmp * num)
                elif sign == "/":
                    tmp = stack.pop()
                    stack.append(tmp / float(num))
                num = 0
                sign = c
            if c == ")":
                break
     
        return sum(stack)

偷懒做法

class Solution:
    def solve(self , s: str) -> int:
        # write code here
        return eval(s)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值