239. 滑动窗口最大值
给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回滑动窗口中的最大值。
思路:
- 使用双端队列实现
- 栈实现的过程中,因为需要维护最大值,以及判断最大值是否失效,因此放入栈中的元素
为对应的index,这样就能够通过判断最左侧的最大值的index是否在滑窗内就行了 - 用双端队列的时候,大的元素一路朝底塞
代码实现
- 双端队列实现
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
n = len(nums)
q = collections.deque()
for i in range(k):
while q and nums[i] >= nums[q[-1]]:
q.pop()
q.append(i)
ans = [nums[q[0]]]
for i in range(k,n):
while q and nums[i] >= nums[q[-1]]:
q.pop()
q.append(i)
while q and i - k >= q[0]:
q.popleft()
ans.append(nums[q[0]])
return ans
- 堆实现
注意事项 - python的heapq是小根堆,没有大根堆,因此这里需要(-value, index) 放入,达到大根堆的目的
- 需要判断当前的堆顶最大值元素是否在时间窗口以内,不在则需要pop堆顶的元素
- 不需要时刻判断heap中的元素是否都在时间窗口以内,只需要判断堆顶元素是否在时间窗内进行了
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
heap = [(-nums[i],i) for i in range(k)]
heapq.heapify(heap)
ans = [0] * (len(nums) - k + 1)
ans[0] = -heap[0][0]
for i in range(k,len(nums)):
heapq.heappush(heap,(-nums[i],i))
while heap[0][1] <= i - k:
heapq.heappop(heap)
ans[i-k+1] = -heap[0][0]
return ans
347.前 K 个高频元素
给定一个非空的整数数组,返回其中出现频率前 k 高的元素。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例 2:
输入: nums = [1], k = 1
输出: [1]
提示:
你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。
你的算法的时间复杂度必须优于
O
(
n
log
n
)
O(n \log n)
O(nlogn) , n 是数组的大小。
题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的。
你可以按任意顺序返回答案
思路
- 和第一题一样使用堆的实现,但是更加的简单,只需要第一次遍历统计一下各个元素的数量,形成一个字典即可,也不需要维护内部元素的有效性,并且直接是使用小根堆jiuxingle
- 使用小根堆
代码实现
import heapq
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
num_count = dict()
for num in nums:
if num not in num_count:
num_count[num] = 1
else:
num_count[num] += 1
print(num_count)
heap = []
i = 0
for key, value in num_count.items():
if i < k:
heapq.heappush(heap, (value, key))
else:
if value > heap[0][0]:
heapq.heappush(heap, (value, key))
heapq.heappop(heap)
i += 1
return [x[1] for x in heap]