代码随想录训练营第十三天|239. 滑动窗口最大值、347.前 K 个高频元素

111 阅读1分钟

239. 滑动窗口最大值 - 力扣(LeetCode)

1. 文章链接

代码随想录 (programmercarl.com)

2. 看到题目的第一想法

有两个困难,

  1. 如何保证快速求出滑动窗口内的最大值。
  2. 如何才能在更新滑动窗口后,立刻知道出去的是不是旧的最大值,进来的是不是新的最大值?

3. 看完代码随想录之后的想法

做成单调递减队列, 也即每次队尾只维护当前窗口内最大的值,右侧则全是降序排列。 如果新元素破了队形,就要更新队列了,但是注意这里不能从队尾pop,而是从队首pop,直到恢复队形。 所以,这个队列中的队尾就是每个窗口的最大值。

4. 实现过程中遇到的困难

太困难了,需要二刷才行。

class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        left_idx = 0
        right_idx = 0
        max_list = []
        decrease_dequeue = deque()
        for num in nums:
            if decrease_dequeue and right_idx - left_idx == k:
                if (nums[left_idx] == decrease_dequeue[0]):
                    decrease_dequeue.popleft()
                left_idx += 1
            while decrease_dequeue and (decrease_dequeue[-1] < num):
                decrease_dequeue.pop()
            decrease_dequeue.append(num)
            right_idx += 1
            if right_idx - left_idx == k:
                max_list.append(decrease_dequeue[0])
        return max_list

5.学习时长

3小时

347. 前 K 个高频元素 - 力扣(LeetCode)

1. 文章链接

代码随想录 (programmercarl.com)

2. 看到题目的第一想法

我不明白怎么把统计的频率求topk后,还能找到他们对应的元素。

3. 看完代码随想录之后的想法

C++中构建一个优先队列,他的比较函数是自定义根据key-value中的value进行比较得到的。 所以他可以实现上面的想法。

4. 实现过程中遇到的困难

import heapq


class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        freq_map = dict()
        for num in nums:
            freq_map[num] = freq_map.get(num, 0) + 1
        small_heap = list()
        for key, freq in freq_map.items():
            heapq.heappush(small_heap, (freq, key))
            if len(small_heap) > k:
                heapq.heappop(small_heap)
        res_list = []
        for freq, key in small_heap:
            res_list.append(key)
        return res_list

注意push和pop的顺序,如果先pop, 那后面的push就会有相应的元素加入,让heap比k长。 如果要先pop,用>=k来限定pop的时机,又逼着heap不得不弹出第k个高频元素,加入一个不确定会不会比pop出的元素频率高的元素,所以是有问题的。

5.学习时长

30分钟。