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

今天主要进行队列的应用训练

239. 滑动窗口最大值

LeetCode - The World's Leading Online Programming Learning Platform

思路:本题如果采用简单的滑动窗口做法, 每次在滑动窗口中循环找到最大值, 可以实现 O(m*n) 负责度的算法。 如果要提升代码的速度, 需要考虑如何记录上一个滑动窗口的最大值已经最大值的位置。 这道题可以采用 优先级对列来处理, 但是这道题采用的是滑动窗口, 优先级队列每次弹出的是最大值,而不是特定位置的值。所以不容易处理。

这道题其实需要注意特定位置的值, 例如队列 [1, 3, -1, 2,1] k=3 我们只需要知道什么时候3 被移除了滑动窗口, 或者移除前有没有比3 还大的元素。  所以可以想到通过 deque 来记录当前滑动窗口内随着下标变高的递减序列。 例如第一个窗口记录 [3, -1], 到了第二个窗口记录 [3, 2]. 实现起来就是, 当滑动窗口移动一次, 如果移出的元素 等于 deque 的 第一位,那么把这个元素从deque 中 pop 出来, 否则不做处理 (例如第一次移动, 1 被移动出来)。 如果移动滑动窗口,新的元素被涵盖进来,比较新元素和 deque 末尾的大小, 如果大于末尾元素, pop 出这个元素, 直到 deque 空了, 或着末尾元素小于等于当前元素。 然后当前元素 push 进去。 

from collections import deque

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

347.前 K 个高频元素

LeetCode - The World's Leading Online Programming Learning Platform

思路:先 count 每个元素出现的次数。然后如果直接排序的话 时间复杂度 O(n*logn). 本题可以采用小顶堆。 count 完成之后把 (count, num)这样的set 放入小顶堆中, 如果小顶堆长度超出K 了, 就 pop 出来一个最小的值。 最后剩的K个元素就是要找的前 K个高频元素。 

import heapq
from collections import Counter

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        c = Counter(nums)
        prio_q = [] # 小顶堆
        for num, freq in c.items():
            heapq.heappush(prio_q, (freq, num))
            if len(prio_q) > k:
                heapq.heappop(prio_q)
        ans = []
        while len(prio_q) > 0:
            _tmp = heapq.heappop(prio_q)
            ans.append(_tmp[1])
        return ans

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
第二十二天的算法训练主要涵盖了Leetcode题目中的三道题目,分别是Leetcode 28 "Find the Index of the First Occurrence in a String",Leetcode 977 "有序数组的平方",和Leetcode 209 "长度最小的子数组"。 首先是Leetcode 28题,题目要求在给定的字符串中找到第一个出现的字符的索引。思路是使用双指针来遍历字符串,一个指向字符串的开头,另一个指向字符串的结尾。通过比较两个指针所指向的字符是否相等来判断是否找到了第一个出现的字符。具体实现的代码如下: ```python def findIndex(self, s: str) -> int: left = 0 right = len(s) - 1 while left <= right: if s[left == s[right]: return left left += 1 right -= 1 return -1 ``` 接下来是Leetcode 977题,题目要求对给定的有序数组中的元素进行平方,并按照非递减的顺序返回结果。这里由于数组已经是有序的,所以可以使用双指针的方法来解决问题。一个指针指向数组的开头,另一个指针指向数组的末尾。通过比较两个指针所指向的元素的绝对的大小来确定哪个元素的平方应该放在结果数组的末尾。具体实现的代码如下: ```python def sortedSquares(self, nums: List[int]) -> List[int]: left = 0 right = len(nums) - 1 ans = [] while left <= right: if abs(nums[left]) >= abs(nums[right]): ans.append(nums[left ** 2) left += 1 else: ans.append(nums[right ** 2) right -= 1 return ans[::-1] ``` 最后是Leetcode 209题,题目要求在给定的数组中找到长度最小的子数组,使得子数组的和大于等于给定的目标。这里可以使用滑动窗口的方法来解决问题。使用两个指针来表示滑动窗口的左边界和右边界,通过移动指针来调整滑动窗口的大小,使得滑动窗口中的元素的和满足题目要求。具体实现的代码如下: ```python def minSubArrayLen(self, target: int, nums: List[int]) -> int: left = 0 right = 0 ans = float('inf') total = 0 while right < len(nums): total += nums[right] while total >= target: ans = min(ans, right - left + 1) total -= nums[left] left += 1 right += 1 return ans if ans != float('inf') else 0 ``` 以上就是第二十二天的算法训练的内容。通过这些题目的练习,可以提升对双指针和滑动窗口算法的理解和应用能力。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值