代码随想录算法训练营第十二天 | 150.逆波兰表达式求值 239.滑动窗口最大值 347.前k个高频元素
python语法:
一、列表、字符串、字典的遍历方式:
列表:1.遍历元素;2.遍历索引;3.enumerate同时获取索引和值;
字符串:1.遍历字符;2.遍历索引;3.enumerate同时获取索引和值;
字典:1.遍历键d;2.遍历键和值d.items();3.遍历值d.values();
二、列表和队列的区别
队列:一种先进先出的数据结构,只允许队尾插入和队首删除,相当于list只能用append()和popleft()
列表:支持随机访问,支持任意位置的插入和删除,使用'colle ctions.deque'
点击查看代码
# 列表遍历示例
lst = [1, 2, 3, 4, 5]
print("遍历列表元素:")
for element in lst:
print(element)
print("\n遍历列表索引:")
for i in range(len(lst)):
print(lst[i])
print("\n使用 enumerate 遍历列表:")
for index, element in enumerate(lst):
print(index, element)
# 字符串遍历示例
s = "hello"
print("\n遍历字符串字符:")
for char in s:
print(char)
print("\n遍历字符串索引:")
for i in range(len(s)):
print(s[i])
print("\n使用 enumerate 遍历字符串:")
for index, char in enumerate(s):
print(index, char)
# 字典遍历示例
d = {'a': 1, 'b': 2, 'c': 3}
print("\n遍历字典键:")
for key in d:
print(key, d[key])
print("\n遍历字典键和值:")
for key, value in d.items():
print(key, value)
print("\n遍历字典值:")
for value in d.values():
print(value)
三、python的堆队列/优先级队列/小顶堆:heapq
点击查看代码
# 创建堆:
import heapq
heap = []
# 向堆中添加元素:
heapq.heappush(heap, item)
# 从堆中取出最小元素:
smallest = heapq.heappop(heap)
# 查看堆中的最小元素而不移除它:
smallest = heap[0]
# 将列表转换为堆:
heapq.heapify(list)
四、map对频率计数,调用 dict.get(key, default) 来获取字典中 key 的值,如果 key 不存在,则返回 default 值(在这里是 0),然后加1。
点击查看代码
# 方法一
map = {}
for i in range(len(nums)):
if nums[i] in map:
map[nums[i]] += 1
else:
map[nums[i]] = 1
# 方法二
map_ = {}
for i in range(len(nums)):
map_[nums[i]] = map_.get(nums[i], 0) + 1
150.逆波兰表达式求值
题目:给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。
请你计算该表达式。返回一个表示表达式值的整数。
解题:
思路:对于后缀式算数表达式(相当于二叉树中的后序遍历),匹配到算符就取近两个数字进行运算得到一个结果,匹配到数字就加入栈。这样很像一个相邻字符串消除的过程,很适合用栈进行对对碰。
关键:定义div函数,'//'表示向下整除,返回的数字就是int整数型,记得区分正负
点击查看代码
def div(x,y):
return x // y if x * y > 0 else -(abs(x) // abs(y))
class Solution:
def evalRPN(self, tokens: List[str]) -> int:
op_map={'+':add,'-':sub,'*':mul,'/':div}
stack=[]
for i in tokens:
if i in ['+','-','*','/']:
s2=stack.pop()
s1=stack.pop()
stack.append(op_map[i](int(s1),int(s2)))
else:
stack.append(i)
return int(stack.pop())
239.滑动窗口最大值
题目:给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
解题:
思路:要用啥数据结构?定义一个队列,放进去窗口里的元素,让后随着窗口的移动,队列也一进push一出pop,返回每个窗口内的最大值getmax。为了能返回每个窗口内的最大值,队列里的元素一定要是有序的,并且把最大值放在出队处。
因此,只需要维护窗口里的最大值的元素,同时保证队列里的元素数值从大到小,这就是单调队列。
关键:设计一个单调队列:(用python双端队列deque()来初始化)
1.pop(value):如果窗口移除的元素value等于单调队列的出口元素,那么队列弹出元素,否则不用任何操作,因为已经在push中弹出了
2.push(value):如果push的元素value大于入口元素的数值,那么就将队列入口的元素弹出,直到push元素的数值小于等于队列入口元素的数值为止
点击查看代码
# 定义一个单调队列,包括pop、push、getmax操作
class MyQueue:
def __init__(self):
self.queue=deque()
def pop(self,value):
if self.queue and value==self.queue[0]:
self.queue.popleft()
def push(self,value):
while self.queue and value>self.queue[-1]:
self.queue.pop()
self.queue.append(value)
def getmax(self):
return self.queue[0]
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
que=MyQueue()
result=[]
for i in range(k):
que.push(nums[i])
result.append(que.getmax())
for i in range(k,len(nums)):
que.pop(nums[i-k])
que.push(nums[i])
result.append(que.getmax())
return result
347.前k个高频元素
题目:给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
解题:
思路:1.统计元素出现频率,用map;2.对频率排序,用优先级队列;3.找出前k个高频元素,用大小为k的小顶堆,这样每次pop的是频率最小值,堆保留频率最高的k个(freq,key)
点击查看代码
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
map={}
for num in nums:
map[num]=map.get(num,0)+1
#定义小顶堆
heap=[]
for key,freq in map.items():
heapq.heappush(heap,(freq,key))
if len(heap)>k:
heapq.heappop(heap)
result=[0]*k
for i in range(k-1,-1,-1):
result[i]=heapq.heappop(heap)[1]
return result

浙公网安备 33010602011771号