232. 用栈实现队列
这道题的关键是理解如何实现先入先出。需要注意的是,python里的list.pop是pop出栈尾元素,也就是pop from back,不是合法操作,所以需要采用两个list来共同模拟栈的操作。
class MyQueue:
def __init__(self):
self.stack_in = []
self.stack_out = []
def push(self, x: int) -> None:
self.stack_in.append(x)
def pop(self) -> int:
if self.empty():
return None
if self.stack_out:
return self.stack_out.pop()
else:
for i in range(len(self.stack_in)):
self.stack_out.append(self.stack_in.pop())
return self.stack_out.pop()
def peek(self) -> int:
ans = self.pop()
self.stack_out.append(ans)
return ans
def empty(self) -> bool:
return not (self.stack_in or self.stack_out)
225. 用队列实现栈
这道题需要注意的事项和上题一致,因为不能pop from back,所以此处使用collections中的数据结构deque来完成数据的存储。
注意,deque的从左边弹出是pop left,不是left pop,务必要注意哦!!
20. 有效的括号
这道题是使用栈来解决问题的经典题目。因为栈的“先入后出”思想非常有利于括号的匹配。有使用字典和不使用字典两种解决方案,但是关键都是需要清晰了解各种决策的边界条件。
使用字典:
class Solution:
def isValid(self, s: str) -> bool:
dic = {'(':')',
'{':'}',
'[':']'}
count = []
for i in s:
if i in dic:
count.append(dic[i])
elif not count or count[-1] != i:
return False
elif i == count.pop():
continue
return False if count else True
不使用字典
class Solution:
def isValid(self, s: str) -> bool:
count = []
for i in s:
if i == '[':
count.append(']')
elif i == '{':
count.append('}')
elif i == '(':
count.append(')')
elif not count or count[-1] != i:
return False
else:
count.pop()
return False if count else True
这种方式会更加节省空间一些。
1047. 删除字符串中所有相邻重复项
首先使用栈解决的方法很简单也很直接了:
class Solution:
def removeDuplicates(self, s: str) -> str:
count = []
for i in s:
if not count or count[-1] != i:
count.append(i)
else:
count.pop()
return ''.join(count)
有些情况下可能面试不允许使用栈,那么可以用双指针来完成。
class Solution:
def removeDuplicates(self, s: str) -> str:
s = list(s)
length = len(s)
fast, slow = 0, 0
while fast < length:
s[slow] = s[fast]
if slow > 0 and s[slow] == s[slow - 1]:
slow -= 1
else:
slow += 1
fast += 1
return ''.join(s[0:slow])
双指针法已经用得非常非常多了,关键是要理解如何进退,如何设定while的边界条件等等。多练习哦!
class Solution:
def removeDuplicates(self, s: str) -> str:
s = list(s)
length = len(s)
fast, slow = 0, 0
while fast < length:
s[slow] = s[fast]
if slow > 0 and s[slow] == s[slow - 1]:
slow -= 1
else:
slow += 1
fast += 1
return ''.join(s[0:slow])
150 逆波兰表达式的求值
这道题关键也是想到要用栈来解决:
class Solution:
def evalRPN(self, tokens: List[str]) -> int:
count = []
for i in tokens:
if i not in '+-*/':
count.append(i)
else:
a = int(count.pop())
b = int(count.pop())
if i == '+': count.append(a+b)
elif i == '-': count.append(b-a)
elif i == '*': count.append(a*b)
else: count.append(b/a)
return int(count.pop())
239. 滑动窗口最大值
这道题的思路其实不简单,但是实行的基本思路确认了之后问题也不是很大。关键是需要了解这种用“单调队列”来进行计数的思想。
from collections import deque
class MyFront:
def __init__(self):
self.queue = deque()
def pop(self, value):
#这个函数是用来在窗口往后挪动的时候,判断是否需要弹出栈顶
if self.queue and self.queue[0] == value:
self.queue.popleft()
def push(self, value):
#这个函数是把新的元素压进来
while self.queue and self.queue[-1] < value:
self.queue.pop()
self.queue.append(value)
def front(self):
return self.queue[0]
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
que = MyFront()
result = []
for i in range(k):
que.push(nums[i])
result.append(que.front())
for i in range(k, len(nums)):
que.pop(nums[i-k])
que.push(nums[i])
result.append(que.front())
return result
347. 前k个高频元素
这道题的关键是想到用大顶堆和小顶堆这两种数据结构。python里自带的heapq就可以用于实现小顶堆,所以知道如何使用即可。
import heapq
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
dic = {}
for i in range(len(nums)):
dic[nums[i]] = dic.get(nums[i], 0) + 1
pri_que = []
for key, freq in dic.items():
heapq.heappush(pri_que, (freq,key))
if len(pri_que) > k:
heapq.heappop(pri_que)
result = [0]*k
for i in range(k-1, -1, -1):
result[i] = heapq.heappop(pri_que)[1]
return result