使用栈实现队列的下列操作:
push(x) – 将一个元素放入队列的尾部。
pop() – 从队列首部移除元素。
peek() – 返回队列首部的元素。
empty() – 返回队列是否为空。
示例:
MyQueue queue = new MyQueue();
queue.push(1);
queue.push(2);
queue.peek(); // 返回 1
queue.pop(); // 返回 1
queue.empty(); // 返回 false
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/implement-queue-using-stacks
思想
简单思想:由于栈是先进先出,队列是先进后出,那么只需要两个栈,即可将顺序理顺。
from collections import deque
class Stack:
def __init__(self):
self.item = deque()
def pop(self):
return self.item.pop()
def push(self, val):
return self.item.append(val)
def top(self):
return self.item[-1]
def __len__(self):
return len(self.item)
class MyQueue(object):
def __init__(self):
"""
Initialize your data structure here.
"""
self.s1 = Stack()
self.s2 = Stack()
def push(self, x):
"""
Push element x to the back of queue.
:type x: int
:rtype: None
"""
self.s1.push(x)
def pop(self):
"""
Removes the element from in front of queue and returns that element.
:rtype: int
"""
if self.s2:
return self.s2.pop()
while self.s1:
val = self.s1.pop()
self.s2.push(val)
return self.s2.pop()
def peek(self):
"""
Get the front element.
:rtype: int
"""
if self.s2:
return self.s2.top()
while self.s1:
val = self.s1.pop()
self.s2.push(val)
return self.s2.top()
def empty(self):
"""
Returns whether the queue is empty.
:rtype: bool
"""
return len(self.s1) == 0 and len(self.s2) == 0
最小栈
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
push(x) —— 将元素 x 推入栈中。
pop() —— 删除栈顶的元素。
top() —— 获取栈顶元素。
getMin() —— 检索栈中的最小元素。
示例:
输入:
[“MinStack”,“push”,“push”,“push”,“getMin”,“pop”,“top”,“getMin”]
[[],[-2],[0],[-3],[],[],[],[]]
输出:
[null,null,null,null,-3,null,0,-2]
解释:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.getMin(); --> 返回 -2.
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/min-stack
思想:用两个栈,其中一个栈正常进出元素,第二个栈在第一个栈进出元素的同时,比较第二个栈的栈顶元素和要进栈的元素大小区别,如果栈顶元素更小,则栈顶元素再次进栈。反之元素进栈。
from collections import deque
class Stack:
def __init__(self):
self.item = deque()
def push(self,x):
self.item.append(x)
def pop(self):
self.item.pop()
def empty(self):
return len(self.item) == 0
def top(self):
return self.item[-1]
class MinStack(object):
def __init__(self):
"""
initialize your data structure here.
"""
self.s = Stack()
self.M_s = Stack()
def push(self, x):
"""
:type x: int
:rtype: None
"""
if self.s.empty():
self.s.push(x)
self.M_s.push(x)
else:
top = self.M_s.top()
if x < top:
self.M_s.push(x)
else:
self.M_s.push(top)
self.s.push(x)
def pop(self):
"""
:rtype: None
"""
self.M_s.pop()
return self.s.pop()
def top(self):
"""
:rtype: int
"""
return self.s.top()
def getMin(self):
"""
:rtype: int
"""
return self.M_s.top()
有效括号
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
示例 1:
输入: “()”
输出: true
示例 2:
输入: “()[]{}”
输出: true
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/valid-parentheses
思想:用栈即可快速实现。若栈顶元素和入栈元素匹配,则将栈顶元素出栈。最后若栈为空,则匹配。若栈不为空,则不匹配
from collections import deque
class Stack():
def __init__(self):
self.item = deque()
def __len__(self):
return len(self.item)
def pop(self):
return self.item.pop()
def push(self,x):
return self.item.append(x)
def empty(self):
return len(self.item) == 0
def top(self):
return self.item[-1]
def get_pair(i):
if i == ')':
return '('
if i == ']':
return '['
if i == '}':
return '{'
class Solution:
def isValid(self, s: str):
if not s:
return True
stack = Stack()
for i in s:
if stack.empty():
stack.push(i)
else:
top = stack.top()
if get_pair(i) == top:
stack.pop()
else:
stack.push(i)
return stack.empty()
两个数组的交集II
给定两个数组,编写一个函数来计算它们的交集。
示例 1:
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2,2]
示例 2:
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[4,9]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/intersection-of-two-arrays-ii
思想:既然是找交集,首先就想到了通过哈希计数,但dict若没有初始值,就会报错,考虑到这个问题,采用defaultdict 来解决。不过一定要注意初始化defaultdict的初始值类型
from collections import defaultdict
class Solution:
def intersect(self, nums1, nums2):
dd = defaultdict(int) # 默认的val值为int
for num in nums1:
dd[num] += 1
res = []
for i in nums2:
if dd[i] > 0:
res.append(i)
dd[i] -= 1
return res
思想2:双指针。
首先对两个数组排序,然后通过快慢指针查找两个数组的子集。若 找到相同元素,则两个指针同时后移,若 第一个数组的当前元素小于 第二个数组的当前元素,则第一个数组后移。若第一个数组的当前元素大于第二个数组的当前元素。第二个数组后移。
class Solution(object):
def intersect(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: List[int]
"""
nums1 = sorted(nums1)
nums2 = sorted(nums2)
r = []
i, j = 0, 0
while i < (len(nums1)) and j < len(nums2):
if nums1[i] < nums2[j]:
i += 1
elif nums1[i] == nums2[j]:
r.append(nums1[i])
i += 1
j += 1
else:
j += 1
return r
运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put 。
获取数据 get(key) - 如果关键字 (key) 存在于缓存中,则获取关键字的值(总是正数),否则返回 -1。
写入数据 put(key, value) - 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字/值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。
进阶:
你是否可以在 O(1) 时间复杂度内完成这两种操作?
示例:
LRUCache cache = new LRUCache( 2 /* 缓存容量 */ );
cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // 返回 1
cache.put(3, 3); // 该操作会使得关键字 2 作废
cache.get(2); // 返回 -1 (未找到)
cache.put(4, 4); // 该操作会使得关键字 1 作废
cache.get(1); // 返回 -1 (未找到)
cache.get(3); // 返回 3
cache.get(4); // 返回 4
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/lru-cache
整理一下:
难点有一下几个:
1、最右侧加入元素(数组 ,队列,链表)
2、最左侧删除元素(数组,队列,链表)
3、可以把最右侧元素后延(链表)
可以实现数据结构:dict + 循环双端链表
但是,好在python提供了一个有序字典OrderedDict
两个操作:
1、get
判断key是否在OrderedDict中,若在,返回对应val,同时通过move_to_end(key)将其移动到最后,若不在,返回-1
2、put
判断key值是否在OrderedDict中,若在,更新key对应的val,若不在将其存入OrderedDict。同时判断OrderedDict的长度,若>预设长度,则通过OrderedDict.popitem(last = False)函数,将最OrderedDict内最左侧元素移除。
from collections import OrderedDict
class LRUCache:
def __init__(self, capacity: int):
self.od = OrderedDict()
self.cap = capacity
def get(self, key: int) -> int:
if key in self.od:
val = self.od[key]
self.od.move_to_end(key)
return val
else:
return -1
def put(self, key: int, value: int) -> None:
if key in self.od:
self.od[key] = value
else:
self.od[key] = value
if len(self.od) > self.cap:
self.od.popitem(last=False)
self.od.move_to_end(key)