1.取最小值。用两个栈来实现,一个普通存数,一个只存相对小的数。不要忘了栈是用列表实现的,列表也能pop,并且有返回值。思路明明正确但提交了好多次,,错在push判断条件上写错了,or左右两边的条件不能随便对调,有顺序的
if not self.tmp or x <= self.tmp[-1]:
class MinStack:
def __init__(self):
self.A, self.B = [], []
def push(self, x):
self.A.append(x)
if not self.B or self.B[-1] >= x: # B 为空或者发现更小的数X,则入栈B
self.B.append(x)
def pop(self):
if self.A.pop() == self.B[-1]: # 可以直接用列表的pop
self.B.pop()
def top(self):
return self.A[-1]
def getMin(self):
return self.B[-1]
2.判断是否能按方法取得/ 判断栈的进出是否合理。注意循环的安放,用for来控制进栈,内置while判断出栈,每出栈一次,计数 i +1
class Solution(object):
def validateBookSequences(self, putIn, takeOut):
"""
:type putIn: List[int]
:type takeOut: List[int]
:rtype: bool
"""
i = 0
stack = []
for num in putIn:
stack.append(num)
while stack and stack[-1] == takeOut[i]: # 判断是否出栈
stack.pop()
i += 1 # 计数i要放在出栈后
return not stack # 如果可以取出则stack为空
3.滑动窗口找窗口最大值(望远镜中的最高海拔)。用暴力可以求,用指针指向窗口的最后一个元素,用两重循环(一重移动窗口,一重建立窗口列表用于找最大值)返回每次查找的窗口最大值。很慢。
class Solution(object):
def maxAltitude(self, heights, limit):
tmp = []
t = []
if not heights:
return tmp
for cnt in range(limit-1, len(heights)):
# tmp.append(max(heights[cnt-2], heights[cnt-1], heights[cnt]))
for i in range(limit):
t.append(heights[cnt-i])
tmp.append(max(t))
t = []
return tmp
K神用的队列求解。用一个双端队列来存一个升序队列:遇到小的数加入队尾,遇到大的数弹出队尾,并加上大的数。每次窗口返回最大值都返回双端队列deque的队头。
import collections
class Solution:
def maxAltitude(self, heights, limit):
if not heights or limit == 0: return []
deque = collections.deque() # 需要import collections
# 未形成窗口
for i in range(limit):
while deque and deque[-1] < heights[i]:
deque.pop()
deque.append(heights[i])
res = [deque[0]]
# 形成窗口后
for i in range(limit, len(heights)):
if deque[0] == heights[i - limit]:
deque.popleft()
while deque and deque[-1] < heights[i]:
deque.pop()
deque.append(heights[i])
res.append(deque[0])
return res
4.自动结算机,用队列实现一系列队列的操作(找最大值,加入队尾,移出队首),要求O(1)。用双端队列deque的pop 和popleft 协助实现O(1)。
# 在本地调试要导入库
import queue
from collections import deque
class Checkout(object):
def __init__(self):
self.queue = queue.Queue() # 定义普通队列
self.deque = deque() # 定义双端队列
def get_max(self):
"""
:rtype: int
"""
return self.deque[0] if self.deque else -1
def add(self, value):
"""
:type value: int
:rtype: None
"""
self.queue.put(value) # queue加队尾
while self.deque and self.deque[-1] < value:
self.deque.pop() # 队尾弹出较小数
self.deque.append(value) # 加入deque
def remove(self):
"""
:rtype: int
"""
if not self.queue:
return -1
val = self.queue.get() # 首元素出列
if self.deque[0] == val:
self.deque.popleft() # 当移出的数为最大值时,deque的队首也要移出
return val
5.找中位数。通过heapq模块(小顶堆,最小元素在根节点)构造一个大顶堆(小顶堆取反)和一个小顶堆保证数据有序,通过根节点取中位数
堆的知识:heapq --- 堆队列算法 — Python 3.12.0 文档
from heapq import *
class MedianFinder:
def __init__(self):
self.A = [] # 小顶堆,保存较大的一半
self.B = [] # 大顶堆,保存较小的一半
def addNum(self, num):
if len(self.A) != len(self.B):
# heapq.heappush(heap, item) 将 item 的值加入 heap 中,保持堆的不变性。
heappush(self.A, num)
heappush(self.B, -heappop(self.A))
# heapq.heappop(heap) 弹出并返回 heap 的最小的元素,保持堆的不变性
else:
heappush(self.B, -num)
heappush(self.A, -heappop(self.B))
def findMedian(self):
return self.A[0] if len(self.A) != len(self.B) else (self.A[0] - self.B[0]) / 2.0