相关推荐
python coding with ChatGPT 打卡第9天| 栈和队列:基础知识
python coding with ChatGPT 打卡第10天| 栈和队列:有效的括号 逆波兰表达式求值
滑动窗口最大值
Key Points
单调队列的经典题目
相关题目
视频讲解
重点分析
暴力解法:
def maxSlidingWindow(nums, k):
i=0
j=i+k
res = []
while j <= len(nums):
res.append(max(nums[i:j]))
i += 1
j += 1
return res
from collections import deque
单调队列:
解释:第一个窗口,3既比1大,又比1活得久,所以1就没有用了。
(对于某一个窗口,更靠右且更大的元素,更可能成为最大值的候选值)
from collections import deque
def maxSlidingWindow(nums, k):
# 如果数组为空或者k为0,则返回空列表
if not nums or k == 0:
return []
# 初始化双端队列和结果列表
deq = deque()
result = []
for i in range(len(nums)):
# 当队列头部元素索引不在滑动窗口内时,将其从队列中移除
if deq and deq[0] < i - k + 1:
deq.popleft()
# 从队列尾部移除所有比当前元素小的元素索引
while deq and nums[i] > nums[deq[-1]]:
deq.pop()
# 将当前元素的索引添加到队列尾部
deq.append(i)
# 当窗口形成时,队列头部元素即为窗口内的最大值
if i >= k - 1:
result.append(nums[deq[0]])
return result
如果不能使用库函数,如 collections.deque,仍然可以使用列表来模拟双端队列的功能。我们将手动实现添加和删除操作来维护窗口内元素的索引。以下是不使用库函数的实现方法:
def maxSlidingWindow(nums, k):
# 如果数组为空或者k为0,则返回空列表
if not nums or k == 0:
return []
# 初始化结果列表和模拟双端队列的列表
result = []
deq = []
for i in range(len(nums)):
# 当队列头部元素索引不在滑动窗口内时,将其从队列中移除
if deq and deq[0] < i - k + 1:
deq.pop(0)
# 从队列尾部移除所有比当前元素小的元素索引
while deq and nums[i] > nums[deq[-1]]:
deq.pop()
# 将当前元素的索引添加到队列尾部
deq.append(i)
# 当窗口形成时,队列头部元素即为窗口内的最大值
if i >= k - 1:
result.append(nums[deq[0]])
return result
前k个高频元素
给定一个非空的整数数组,返回其中出现频率前 k 高的元素。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例 2:
输入: nums = [1], k = 1
输出: [1]
Key Points
时间复杂度的优化:
无需全部排序(nlogn),秩序维护k个有序集合即可
相关题目
视频讲解
重点分析
暴力解法:
def topKFrequent(nums, k):
nums_count = {}
for x in nums:
nums_count[x] = nums_count.get(x, 0) + 1
nums_sort = sorted(nums_count.items(), key=lambda x:x[1], reverse=True)
res = []
for i in range(k):
res.append(nums_sort[i][0])
return res
import heapq
def topKFrequent(nums, k):
# 构建频率哈希表
nums_count = {}
for num in nums:
nums_count[num] = nums_count.get(num, 0) + 1
# 构建最小堆,堆的大小为 k
# 堆中的元素是一个元组,结构为 (频率, 元素)
min_heap = []
for num, freq in nums_count.items():
heapq.heappush(min_heap, (freq, num))
if len(min_heap) > k:
heapq.heappop(min_heap)
# 从最小堆中提取元素,构建结果列表
result = [heapq.heappop(min_heap)[1] for _ in range(k)]
return result[::-1] # 可能需要反转列表以得到正确的顺序
如果不能用库函数呢?
如果不能使用库函数,我们可以手动实现一个最小堆。最小堆是一种常见的数据结构,用于高效地管理优先级队列。以下是不使用库函数实现的代码:
def topKFrequent(nums, k):
# 构建频率哈希表
nums_count = {}
for num in nums:
nums_count[num] = nums_count.get(num, 0) + 1
# 手动实现最小堆
def heapify(arr, n, i):
smallest = i
l = 2 * i + 1
r = 2 * i + 2
if l < n and arr[l][0] < arr[smallest][0]:
smallest = l
if r < n and arr[r][0] < arr[smallest][0]:
smallest = r
if smallest != i:
arr[i], arr[smallest] = arr[smallest], arr[i]
heapify(arr, n, smallest)
def insertHeap(arr, num):
size = len(arr)
if size < k:
arr.append(num)
size += 1
elif num[0] > arr[0][0]:
arr[0] = num
heapify(arr, size, 0)
# 构建最小堆
min_heap = []
for num, freq in nums_count.items():
insertHeap(min_heap, (freq, num))
# 从最小堆中提取元素,构建结果列表
result = [item[1] for item in min_heap]
return result
# 测试函数
print(topKFrequent([1, 1, 1, 2, 2, 3], 2)) # 输出应为 [1, 2]