栈与队列 232. 用栈实现队列 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):
实现 MyQueue 类:
void push(int x) 将元素 x 推到队列的末尾
int pop() 从队列的开头移除并返回元素
int peek() 返回队列开头的元素
boolean empty() 如果队列为空,返回 true ;否则,返回 false
说明:
你 只能 使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
示例 1:
1 2 3 4 5 6 7 8 9 10 11 12 13 输入: ["MyQueue", "push", "push", "peek", "pop", "empty"] [[], [1], [2], [], [], []] 输出: [null, null, null, 1, 1, false] 解释: MyQueue myQueue = new MyQueue(); myQueue.push(1); // queue is: [1] myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue) myQueue.peek(); // return 1 myQueue.pop(); // return 1, queue is [2] myQueue.empty(); // return false
提示:
1 <= x <= 9
最多调用 100 次 push、pop、peek 和 empty
假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)
进阶:
你能否实现每个操作均摊时间复杂度为 O(1) 的队列?换句话说,执行 n 个操作的总时间复杂度为 O(n) ,即使其中一个操作可能花费较长时间。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class MyQueue : def __init__ (self ): self .inStack = [] self .outStack = [] def push (self, x: int ) -> None : while len (self .outStack) > 0 : self .inStack.append(self .outStack.pop()) self .inStack.append(x) while len (self .inStack) > 0 : self .outStack.append(self .inStack.pop()) def pop (self ) -> int : return self .outStack.pop() def peek (self ) -> int : return self .outStack[-1 ] def empty (self ) -> bool : return len (self .outStack) == 0
225. 用队列实现栈 请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。
实现 MyStack 类:
void push(int x) 将元素 x 压入栈顶。
int pop() 移除并返回栈顶元素。
int top() 返回栈顶元素。
boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。
注意:
你只能使用队列的标准操作 —— 也就是 push to back、peek/pop from front、size 和 is empty 这些操作。
你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 输入: ["MyStack", "push", "push", "top", "pop", "empty"] [[], [1], [2], [], [], []] 输出: [null, null, null, 2, 2, false] 解释: MyStack myStack = new MyStack(); myStack.push(1); myStack.push(2); myStack.top(); // 返回 2 myStack.pop(); // 返回 2 myStack.empty(); // 返回 False
提示:
1 <= x <= 9
最多调用100 次 push、pop、top 和 empty
每次调用 pop 和 top 都保证栈不为空
**进阶:**你能否仅用一个队列来实现栈。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 from collections import dequeclass MyStack : def __init__ (self ): self .Stack1 = deque() self .Stack2 = deque() self .data = 1 def push (self, x: int ) -> None : emptyS, dataS = (self .Stack1, self .Stack2) if self .data == 2 else (self .Stack2, self .Stack1) emptyS.appendleft(x) while len (dataS) > 0 : emptyS.appendleft(dataS.pop()) self .data = 1 if self .data == 2 else 2 def pop (self ) -> int : dataS = self .Stack1 if self .data == 1 else self .Stack2 return dataS.pop() def top (self ) -> int : dataS = self .Stack1 if self .data == 1 else self .Stack2 return dataS[-1 ] def empty (self ) -> bool : dataS = self .Stack1 if self .data == 1 else self .Stack2 return len (dataS) == 0
20. 有效的括号 给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
每个右括号都有一个对应的相同类型的左括号。
示例 1:
**输入:**s = “()”
**输出:**true
示例 2:
**输入:**s = “()[]{}”
**输出:**true
示例 3:
**输入:**s = “(]”
**输出:**false
示例 4:
**输入:**s = “([])”
**输出:**true
示例 5:
**输入:**s = “([)]”
**输出:**false
提示:
1 <= s.length <= 104
s 仅由括号 '()[]{}' 组成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Solution : def isValid (self, s: str ) -> bool : mapDict = { ']' :'[' , ')' :'(' , '}' : '{' } stack = [] for char in s: if char in mapDict.values(): stack.append(char) else : if len (stack) == 0 or stack[-1 ] != mapDict[char]: return False else : stack.pop() return len (stack) == 0
1047. 删除字符串中的所有相邻重复项 给出由小写字母组成的字符串 s,重复项删除操作 会选择两个相邻且相同的字母,并删除它们。
在 s 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
示例:
1 2 3 4 输入:"abbaca" 输出:"ca" 解释: 例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"。
提示:
1 <= s.length <= 105
s 仅由小写英文字母组成。
1 2 3 4 5 6 7 8 9 10 class Solution : def removeDuplicates (self, s: str ) -> str : stack = [] for idx in range (len (s)): if len (stack) > 0 and stack[-1 ] == s[idx]: stack.pop() else : stack.append(s[idx]) return '' .join(stack)
150. 逆波兰表达式求值 给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。
请你计算该表达式。返回一个表示表达式值的整数。
注意:
有效的算符为 '+'、'-'、'*' 和 '/' 。
每个操作数(运算对象)都可以是一个整数或者另一个表达式。
两个整数之间的除法总是 向零截断 。
表达式中不含除零运算。
输入是一个根据逆波兰表示法表示的算术表达式。
答案及所有中间计算结果可以用 32 位 整数表示。
示例 1:
1 2 3 输入:tokens = ["2","1","+","3","*"] 输出:9 解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9
示例 2:
1 2 3 输入:tokens = ["4","13","5","/","+"] 输出:6 解释:该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6
示例 3:
1 2 3 4 5 6 7 8 9 10 输入:tokens = ["10","6","9","3","+","-11","*","/","*","17","+","5","+"] 输出:22 解释:该算式转化为常见的中缀算术表达式为: ((10 * (6 / ((9 + 3) * -11))) + 17) + 5 = ((10 * (6 / (12 * -11))) + 17) + 5 = ((10 * (6 / -132)) + 17) + 5 = ((10 * 0) + 17) + 5 = (0 + 17) + 5 = 17 + 5 = 22
提示:
1 <= tokens.length <= 104
tokens[i] 是一个算符("+"、"-"、"*" 或 "/"),或是在范围 [-200, 200] 内的一个整数
逆波兰表达式:
逆波兰表达式是一种后缀表达式,所谓后缀就是指算符写在后面。
平常使用的算式则是一种中缀表达式,如 ( 1 + 2 ) * ( 3 + 4 ) 。
该算式的逆波兰表达式写法为 ( ( 1 2 + ) ( 3 4 + ) * ) 。
逆波兰表达式主要有以下两个优点:
去掉括号后表达式无歧义,上式即便写成 1 2 + 3 4 + * 也可以依据次序计算出正确结果。
适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import mathclass Solution : def evalRPN (self, tokens: List [str ] ) -> int : stack = [] op = {'+' , '-' , '*' , '/' } for char in tokens: if char not in op: stack.append(char) else : num2 = stack.pop() num1 = stack.pop() if char == '+' : stack.append(str (int (num1) + int (num2))) elif char == '-' : stack.append(str (int (num1) - int (num2))) elif char == '*' : stack.append(str (int (num1) * int (num2))) elif char == '/' : ans = int (num1) / int (num2) stack.append(str (math.floor(ans)) if ans>0 else str (math.ceil(ans))) return int (stack[0 ])
239. 滑动窗口最大值 给你一个整数数组 nums,有一个大小为 k的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
示例 1:
1 2 3 4 5 6 7 8 9 10 11 输入:nums = [1,3,-1,-3,5,3,6,7], k = 3 输出:[3,3,5,5,6,7] 解释: 滑动窗口的位置 最大值 --------------- ----- [1 3 -1] -3 5 3 6 7 3 1 [3 -1 -3] 5 3 6 7 3 1 3 [-1 -3 5] 3 6 7 5 1 3 -1 [-3 5 3] 6 7 5 1 3 -1 -3 [5 3 6] 7 6 1 3 -1 -3 5 [3 6 7] 7
示例 2:
1 2 输入:nums = [1], k = 1 输出:[1]
提示:
1 <= nums.length <= 105
-104 <= nums[i] <= 104
1 <= k <= nums.length
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class Solution : def maxSlidingWindow (self, nums: List [int ], k: int ) -> List [int ]: if k == 1 : return nums from collections import deque res = [] q = deque() for i in range (len (nums)): while q and nums[i] >= nums[q[-1 ]]: q.pop() q.append(i) left = i - k + 1 if q[0 ] < left: q.popleft() if left >= 0 : res.append(nums[q[0 ]]) return res
347. 前 K 个高频元素 给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
示例 1:
**输入:**nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例 2:
**输入:**nums = [1], k = 1
输出: [1]
示例 3:
**输入:**nums = [1,2,1,2,1,2,3,1,3,2], k = 2
输出: [1,2]
提示:
1 <= nums.length <= 105
-104 <= nums[i] <= 104
k 的取值范围是 [1, 数组中不相同的元素的个数]
题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的
**进阶:**你所设计算法的时间复杂度 必须 优于 O(n log n) ,其中 n是数组大小。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 from heapq import *class Solution : def topKFrequent (self, nums: List [int ], k: int ) -> List [int ]: class Item : def __init__ (self, num, times ): self .num = num self .times = times Item.__lt__ = lambda a, b: a.times> b.times d = {} for num in nums: if num in d.keys(): d[num] += 1 else : d[num] = 1 items = [] for key, value in d.items(): items.append(Item(key, value)) heapify(items) res = [] for _ in range (k): res.append(heappop(items).num) return res