代码随想录算法训练营Day 11|239: 滑动窗口最大值,347. 前 K 个高频元素

题目简介

239: 滑动窗口最大值
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回 滑动窗口中的最大值 。

347. 前 K 个高频元素
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。

初见思路

  1. 初见的时候想Python特性直接暴力解
class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        if len(nums) == 1:
            return [nums[0]]

        ans = list()
        for i in range(len(nums) - k  + 1):
            window = nums[i:i+k]
            window.sort()
            ans.append(window[-1])

        return ans

天真了,这样肯定超时;结合这两天的主题,应该是队列或者堆的方式,自然的我们会想维护一个单调的栈或队列。构建一个队列来记录窗口的最大值:

class MaxQueue:
    def __init__(self):
        self.queue = deque()

    def front(self):
        return self.queue[0]

    def push(self,val):
        while self.queue and val > self.queue[-1]:
            self.queue.pop()
        self.queue.append(val)

    def pop(self,val):
        if self.queue and val == self.queue[0]:
            self.queue.popleft()

结合这个单调队列,可以得到下方的解:

class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        q = MaxQueue()
        ans = list()
        for i in range(k):
            q.push(nums[i])
        ans.append(q.front())
        for i in range(k,len(nums)):
            q.pop(nums[i - k])
            q.push(nums[i])
            ans.append(q.front())
        
        return ans
  1. 其实这道题不涉及栈和队列的知识的知识也能暴力解出来,用字典。
class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        hash_map = dict()

        for num in nums:
            hash_map[num] = hash_map.get(num,0) + 1

        ans = list()
        i = 0
        for key,val in sorted(hash_map.items(),key=lambda x:-x[1]):
            if i == k: break
            ans.append(key)
            i += 1

        return ans

复盘思路

在LC上对239有一种优化思路,我们可以简化队列存储的内容,实际上存储元素的下标就可以了:

class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        if not nums or k<=0:
            return []
        res = []
        q = collections.deque()
        for i in range(len(nums)):
            if q and i-k == q[0]:
                q.popleft()
            while q and nums[i]>nums[q[-1]]:
                q.pop()
            q.append(i)
            if i>=k-1:
                res.append(nums[q[0]])
        return res

对于347,随想录给出的解法主要是教导人们heapq的用法:

import heapq
class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        #要统计元素出现频率
        map_ = {} #nums[i]:对应出现的次数
        for i in range(len(nums)):
            map_[nums[i]] = map_.get(nums[i], 0) + 1
        
        #对频率排序
        #定义一个小顶堆,大小为k
        pri_que = [] #小顶堆
        
        #用固定大小为k的小顶堆,扫描所有频率的数值
        for key, freq in map_.items():
            heapq.heappush(pri_que, (freq, key))
            if len(pri_que) > k: 
                heapq.heappop(pri_que)
        
        print(pri_que)
        #找出前K个高频元素,因为小顶堆先弹出的是最小的,所以倒序来输出到数组
        result = [0] * k
        for i in range(k-1, -1, -1):
            result[i] = heapq.heappop(pri_que)[1]
        return result

重点难点

https://programmercarl.com/0239.%E6%BB%91%E5%8A%A8%E7%AA%97%E5%8F%A3%E6%9C%80%E5%A4%A7%E5%80%BC.html

https://programmercarl.com/0347.%E5%89%8DK%E4%B8%AA%E9%AB%98%E9%A2%91%E5%85%83%E7%B4%A0.html

今日收获

  1. 单调队列
  2. Python中堆的使用 - heapq
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容