leetcode(22)栈和队列系列题目

20. 有效的括号

用字典存匹配的括号
比较栈里第一个元素的值与当前括号
考过两次

class Solution:
    def isValid(self, s: str) -> bool:
        dic = {'{': '}', '[': ']', '(': ')','?': '?'}
        stack = ['?']
        for ch in s:
            if ch in dic:
                stack.append(ch)
            elif dic[stack.pop()] != ch:
                return False
        return len(stack) == 1

622. 设计循环队列

class MyCircularQueue:

    def __init__(self, k: int):
        self.size = k + 1  # 因为循环队列需要空一个
        self.front = 0
        self.rear = 0        
        # self.queue = [0] * (k + 1)
        self.queue = [0 for _ in range(k+1)]

    def enQueue(self, value: int) -> bool:
        if self.isFull():
            return False
        else:
            self.rear = (self.rear + 1) % self.size
            self.queue[self.rear] = value
            return True

    def deQueue(self) -> bool:
        if self.isEmpty():
            return False
        else:
            self.front = (self.front + 1) % self.size
            return True

    def Front(self) -> int:
        """返回头部所指的元素:注意是下一个,因为有一个一直空着"""
        if self.isEmpty():
            return -1
        else:
            return self.queue[(self.front + 1) % self.size]

    def Rear(self) -> int:
        if self.isEmpty():
            return -1
        else:
            return self.queue[self.rear]

    def isEmpty(self) -> bool:
        return self.front == self.rear

    def isFull(self) -> bool:
        """判断队满:注意队满的是队首和队尾之间空着一个"""
        return self.front == (self.rear + 1) % self.size

641. 设计循环双端队列

  1. 初始化容量size = k + 1,并建立大小为size的数组deque;还需要两个指针front和rear,front指向数组中第一个数据位置,rear指向数组中下一个可存储的空位置。也是因为rear总是指向空位置,所以之前初始化容量的时候多加了一个1
  2. 判空条件:front == rear
    判满条件:(rear + 1) % capacity == front
    也就是rear再后移一位就碰到了front,因为是循环存储的,所以rear + 1可能会比capacity大,取模之后再和front比较
  3. 需要注意代码中对rear和front的所有 + 1 或 - 1 操作都需要取模,因为都可能超出数组下标范围,并且 - 1 操作因为还可能导致产生负数,还需要再加一个size避免产生负数。比如front = (front - 1 + size) % size
class MyCircularDeque:
    def __init__(self, k: int):
        self.size = k + 1
        self.front = 0
        self.rear = 0
        self.queue = [0] * (k + 1)

    def insertFront(self, value: int) -> bool:
        if self.isFull():
            return False
        else:
            self.front = (self.front - 1 + self.size) % self.size  ##
            self.queue[self.front] = value
            return True

    def insertLast(self, value: int) -> bool:
        if self.isFull():
            return False
        else:
            self.queue[self.rear] = value   # 注意先赋值再移动rear的位置
            self.rear = (self.rear + 1) % self.size  ##            
            return True

    def deleteFront(self) -> bool:
        if self.isEmpty():
            return False
        else:
            self.front = (self.front + 1) % self.size
            return True

    def deleteLast(self) -> bool:
        if self.isEmpty():
            return False
        else:
            self.rear = (self.rear - 1 + self.size) % self.size  ##
            return True

    def getFront(self) -> int:
        if self.isEmpty():
            return -1
        else:
            return self.queue[self.front]

    def getRear(self) -> int:
        if self.isEmpty():
            return -1
        else:
            return self.queue[(self.rear - 1 + self.size) % self.size]  ##

    def isEmpty(self) -> bool:
        return self.front == self.rear

    def isFull(self) -> bool:
        return self.front == (self.rear + 1) % self.size

1670. 设计前中后队列

class FrontMiddleBackQueue:

    def __init__(self):
        self.q = []

    def pushFront(self, val: int) -> None:
        self.q.insert(0, val)

    def pushMiddle(self, val: int) -> None:
        self.q.insert(len(self.q) // 2, val)

    def pushBack(self, val: int) -> None:
        self.q.append(val)

    def popFront(self) -> int:
        if self.q:
            return self.q.pop(0)
        return -1

    def popMiddle(self) -> int:
        if self.q:
            return self.q.pop((len(self.q) - 1) // 2)  # 注意-1
        return -1

    def popBack(self) -> int:
        if self.q:
            return self.q.pop(-1)
        return -1

933. 最近的请求次数

t代表这个员工的工号,每次新员工t加入q公司前先把工号小于t -3000的老家伙都辞退,然后再让t入职,统计q公司现有几个员工

class RecentCounter:

    def __init__(self):
        self.queue = deque()

    def ping(self, t: int) -> int:
        self.queue.append(t)
        while self.queue and t - 3000 > self.queue[0]:
            self.queue.popleft()
        
        return len(self.queue) 

面试题 17.09. 第 k 个数

class Solution:
    def getKthMagicNumber(self, k: int) -> int:
        # 使用小顶堆处理(因为每次需要得到最小的数字)
        heap = [1]  # 第一个元素是1
        for _ in range(k):
            res = heapq.heappop(heap)  # 每次取出堆中的首元素(最小元素)
            while heap and res == heap[0]:  # 去除重复元素
                heapq.heappop(heap)
            heapq.heappush(heap, res * 3)  # 依次将当前元素乘以3,5,7的值压入堆中
            heapq.heappush(heap, res * 5)
            heapq.heappush(heap, res * 7)
        return res

1106. 解析布尔表达式

从左到右遍历表达式 expression,对于遍历到的每个字符 cc:

如果 e 是 "tf!&|" 中的一个,直接将其入栈;
如果 e 是右括号 ')',将栈中元素依次出栈,直到遇到操作符 '!' 或 '&' 或 '|'。过程中用变量 t 和 f 记录出栈字符中 't' 和 'f' 的个数。最后根据出栈字符的个数和操作符计算得到新的字符 't' 或 'f',并将其入栈。
遍历完表达式 expression 后,栈中只剩下一个字符,如果是 't',返回 true,否则返回 false。

class Solution:
    def parseBoolExpr(self, expression: str) -> bool:
        stk = []
        for e in expression:
            if e in 'tf!&|':
                stk.append(e)
            elif e == ')':
                t = f = 0
                while stk[-1] in 'tf':
                    t += stk[-1] == 't'
                    f += stk[-1] == 'f' 
                    stk.pop()
                match stk.pop():
                    case '!':
                        c = 'f' if t else 't'
                    case '&':
                        c = 'f' if f else 't'
                    case '|' :
                        c = 't' if t else 'f'
                stk.append(c)
        return stk[0] == 't'

155. 最小栈

使用辅助栈

class MinStack:

    def __init__(self):
        self.st = []
        self.min_st = []

    def push(self, val: int) -> None:
        self.st.append(val)
        if not self.min_st or val <= self.min_st[-1]:
            self.min_st.append(val)

    def pop(self) -> None:  
        if self.st.pop() == self.min_st[-1]:
            self.min_st.pop()

    def top(self) -> int:
        return self.st[-1]

    def getMin(self) -> int:
        return self.min_st[-1]



# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(val)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.getMin()

895. 最大频率栈

自己的写法:

class FreqStack:

    def __init__(self):
        self.stack = []
        self.cnt = defaultdict(int)

    def push(self, val: int) -> None:
        self.stack.append(val)
        self.cnt[val] += 1

    def pop(self) -> int:
        most_freq = max(self.cnt.values())
        for i in range(len(self.stack) - 1, -1, -1):
            if self.cnt[self.stack[i]] == most_freq:
                res = self.stack[i]
                self.cnt[self.stack[i]] -= 1
                self.stack.pop(i)
                return res

# Your FreqStack object will be instantiated and called as such:
# obj = FreqStack()
# obj.push(val)
# param_2 = obj.pop()

优化后的方法:哈希表 + 优先队列(大根堆)O(logn)

class FreqStack:

    def __init__(self):
        self.q = []
        self.cnt = defaultdict(int)
        self.ts = 0

    def push(self, val: int) -> None:
        self.ts += 1
        self.cnt[val] += 1
        # 记录每次压入栈中的次数和索引,默认栈顶是最小值,因此取反
        heappush(self.q, (-self.cnt[val], -self.ts, val))

    def pop(self) -> int:
        res = heappop(self.q)[2]
        self.cnt[res] -= 1
        return res

# Your FreqStack object will be instantiated and called as such:
# obj = FreqStack()
# obj.push(val)
# param_2 = obj.pop()

进一步优化:双哈希表 O(1)

class FreqStack:

    def __init__(self):
        self.fre = defaultdict(list)
        self.cnt = defaultdict(int)
        self.mx = 0

    def push(self, val: int) -> None:
        self.cnt[val] += 1  # 记录元素出现的频率
        self.fre[self.cnt[val]].append(val)  # 记录该频率的元素
        self.mx = max(self.mx, self.cnt[val])

    def pop(self) -> int:
        res = self.fre[self.mx].pop()
        self.cnt[res] -= 1
        if not self.fre[self.mx]:
            self.mx -= 1 
        return res

# Your FreqStack object will be instantiated and called as such:
# obj = FreqStack()
# obj.push(val)
# param_2 = obj.pop()

posted @   YTT77  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示
点击右上角即可分享
微信分享提示