代码随想录算法训练营第十一天 | 栈与队列part02
150 逆波兰表达式求值
思路:用栈来进行数字的存储,遇见数字就存入栈中,遇见操作符就从栈中取出元素,做一个计算,然后再加入栈中。
自己做的,代码并不规范,但是力扣可以通过
tokens = ["4","-2","/","2","-3","-","-"]
stack_in = []
for i in tokens:
if i != '+' and i != '-' and i != '*' and i != '/':
stack_in.append(i)
else :
x1 = int(stack_in.pop())
x2 = int(stack_in.pop())
if i == '+':
stack_in.append(x2+x1)
elif i == '-':
stack_in.append(x2-x1)
elif i == '*':
stack_in.append(x2*x1)
elif i == '/':
if x2//x1 < 0:
if x2 % x1 == 0 :
stack_in.append(x2//x1)
else :
stack_in.append(x2//x1 + 1)
else :
stack_in.append(x2//x1)
print(stack_in)
参考代码:虽然没有快多少,但是代码很简洁。
from operator import add, sub, mul
def div(x, y):
# 使用整数除法的向零取整方式
return int(x / y) if x * y > 0 else -(abs(x) // abs(y))
class Solution(object):
op_map = {'+': add, '-': sub, '*': mul, '/': div}
def evalRPN(self, tokens):
stack = []
for token in tokens:
if token not in {'+', '-', '*', '/'}:
stack.append(int(token))
else:
op2 = stack.pop()
op1 = stack.pop()
stack.append(self.op_map[token](op1, op2)) # 第一个出来的在运算符后面
return stack.pop()
239 滑动窗口最大值 (有点难度,可能代码写不出来,但一刷至少需要理解思路)
正常思路如下,直接存一下每个滑动窗口的最大值,暴力解法,时间复杂度为o(n*k),在力扣上有很多测试点过不去。
nums = [1,3,-1,-3,5,3,6,7]
k = 3
# nums = [1]
# k = 1
slow = 0
fast = slow + k
stack = []
while fast <= len(nums):
max_ = nums[slow]
for i in range(slow,fast):
max_ = nums[i] if nums[i] > max_ else max_
stack.append(max_)
slow += 1
fast += 1
print(stack)
优化思路:
双端队列(deque) :我们用双端队列来保存窗口内的元素索引,并确保队列的元素满足以下条件:
- 队列中的元素按照从大到小的顺序排列。
- 队列的第一个元素总是当前窗口的最大值(即队列的头部元素)。
滑动窗口:
- 对于每个新的元素,我们移除队列中不再可能成为最大值的元素。
- 每次滑动窗口时,队列中的头部元素是当前窗口的最大值。
from collections import deque # 引入双端队列(deque)
def maxSlidingWindow(nums, k):
result = [] # 用来保存结果
dq = deque() # 初始化双端队列
for i in range(len(nums)): # 遍历每一个元素
# 1. 移除不在窗口内的元素(即队列头部的索引小于当前窗口的左边界)
if dq and dq[0] < i - k + 1:
dq.popleft() # popleft() 弹出队列头部的元素
# 2. 移除队列中所有比当前元素小的索引
while dq and nums[dq[-1]] < nums[i]:
dq.pop() # pop() 弹出队列尾部的元素
# 3. 将当前元素的索引加入队列
dq.append(i)
# 4. 当窗口大小达到k时,记录当前窗口的最大值
if i >= k - 1:
result.append(nums[dq[0]]) # 队列头部的索引对应的是当前窗口的最大值
return result
详细的执行过程:
假设 nums = [1, 3, -1, -3, 5, 3, 6, 7],k = 3,我们来逐步执行代码。
-
i = 0,
nums[i] = 1:- 队列为空,直接把索引
0加入队列。 - 队列:
[0]。
- 队列为空,直接把索引
-
i = 1,
nums[i] = 3:nums[1]比队列中的元素nums[0] = 1大,移除队列尾部的元素。- 队列变为空,加入索引
1。 - 队列:
[1]。
-
i = 2,
nums[i] = -1:nums[2]比队列中的元素nums[1] = 3小,不需要移除。- 加入索引
2。 - 队列:
[1, 2]。 - 当前窗口大小为 3,队列头部索引
1对应的值是3,所以当前窗口最大值是3。
-
i = 3,
nums[i] = -3:nums[3]比队列中的元素nums[2] = -1小,不需要移除。- 加入索引
3。 - 队列:
[1, 2, 3]。 - 当前窗口最大值仍是
3。
-
i = 4,
nums[i] = 5:nums[4]比队列中的元素nums[3] = -3、nums[2] = -1、nums[1] = 3都大,依次移除队列尾部的元素。- 队列:
[4]。 - 当前窗口最大值是
5。
-
i = 5,
nums[i] = 3:nums[5]比队列中的元素nums[4] = 5小,不移除。- 加入索引
5。 - 队列:
[4, 5]。 - 当前窗口最大值是
5。
-
i = 6,
nums[i] = 6:nums[6]比队列中的元素nums[5] = 3、nums[4] = 5都大,依次移除队列尾部的元素。- 队列:
[6]。 - 当前窗口最大值是
6。
-
i = 7,
nums[i] = 7:nums[7]比队列中的元素nums[6] = 6大,移除队列尾部的元素。- 加入索引
7。 - 队列:
[7]。 - 当前窗口最大值是
7。
347 前 K 个高频元素 (有点难度,可能代码写不出来,一刷至少需要理解思路)
nums = [1,1,1,2,2,3]
k = 2
dict_ = dict()
for i in nums:
dict_[i] = dict_.get(i,0) + 1
dict_ = sorted(dict_.items(),key=lambda x:x[1],reverse=True)
list_ = []
for i in dict_[:k]:
list_.append(i[0])
print(list_)