代码随想录 Day10 | Leetcode239 滑动窗口最大值、Leetcode 347 前 K 个高频元素

文章介绍了在LeetCode中的两个编程问题:如何使用单调栈解决滑动窗口中最大值的问题,以及利用堆数据结构找出数组中出现频率前k高的元素。作者详细阐述了算法思路和Python代码实现,强调了时间复杂度的要求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代码随想录系列

1.代码随想录Day1

2.代码随想录Day2

3.代码随想录Day3

4.代码随想录Day4

5.代码随想录Day5

6.代码随想录Day6

7.代码随想录Day7

8.代码随想录Day8

9.代码随想录Day9

上题

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

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

一、第一题

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
示例 1:
    输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
    输出:[3,3,5,5,6,7]
    解释:
    滑动窗口的位置                最大值
    ---------------               -----
    [1  3  -1] -3  5  3  6  7       3
    1 [3  -1  -3] 5  3  6  7       3
    1  3 [-1  -3  5] 3  6  7       5
    1  3  -1 [-3  5  3] 6  7       5
    1  3  -1  -3 [5  3  6] 7       6
    1  3  -1  -3  5 [3  6  7]      7

    示例 2:
    输入:nums = [1], k = 1
    输出:[1]

    提示:
    1 <= nums.length <= 105
    -104 <= nums[i] <= 104
    1 <= k <= nums.length
    """

思路

  • 单调栈。。。。
  • 遍历列表nums,未达到窗口长度时,不断入队出队,保留最大值,存放在re=[]里,所以,当i==k时,re里仅有一个元素
  • re存储的是当前窗口的元素,并且从左到右递减,窗口最大值直接取re[0]即可
  • 所以每入队一个元素,nums[i],需要把re里小于nums[i]的元素全部删除,最终re[i]一定是整个窗口里的最小值
  • re[0] == nums[i],则re[0]出队
  • 窗口移动时,如果re里存在窗口最左边的元素需要把该元素从re移除
# 窗口移动一次移除num[i-1],若num[i-1]在re内存在,则一定是re内当前的最大值,因为num[i-1]已经经过三次轮换,re最多存放窗口长度数量的元素
if re[0] == nums[i - k]:
    re.pop(0)

代码

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

    示例 1:
    输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
    输出:[3,3,5,5,6,7]
    解释:
    滑动窗口的位置                最大值
    ---------------               -----
    [1  3  -1] -3  5  3  6  7       3
    1 [3  -1  -3] 5  3  6  7       3
    1  3 [-1  -3  5] 3  6  7       5
    1  3  -1 [-3  5  3] 6  7       5
    1  3  -1  -3 [5  3  6] 7       6
    1  3  -1  -3  5 [3  6  7]      7

    示例 2:
    输入:nums = [1], k = 1
    输出:[1]

    提示:
    1 <= nums.length <= 105
    -104 <= nums[i] <= 104
    1 <= k <= nums.length
    """

    def maxSlidingWindow(self, nums, k):
        if not nums and k == 0:
            return
        re = []
        result = []

        # 窗口未形成
        for i in range(k):
            # 单调栈,re内小于nums[i]的均删除,再把nums[i]加入队列尾,保证从左到右递减,最大值则直接从队列头取出
            while re and re[-1] < nums[i]:
                re.pop()
            re.append(nums[i])
        result.append(re[0])

        # 窗口已形成
        for i in range(k, len(nums)):
            # 窗口移动一次移除num[i-1],若num[i-1]在re内存在,则一定是re内当前的最大值,因为num[i-1]已经经过三次轮换,re最多存放窗口长度数量的元素
            if re[0] == nums[i - k]:
                re.pop(0)
            while re and re[-1] < nums[i]:
                re.pop()
            re.append(nums[i])
            result.append(re[0])
        return result


if __name__ == '__main__':
    test = Solution()
    nums = [[1, 3, -1, -3, 5, 3, 6, 7], [1]]
    k = [3, 1]
    for i in range(len(nums)):
        print(test.maxSlidingWindow(nums[i], k[i]))

二、第二题

给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
    示例 1:
    输入: nums = [1,1,1,2,2,3], k = 2
    输出: [1,2]

    示例 2:
    输入: nums = [1], k = 1
    输出: [1]

    提示:
    1 <= nums.length <= 105
    k 的取值范围是 [1, 数组中不相同的元素的个数]
    题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的

    进阶:你所设计算法的时间复杂度 必须 优于 O(n log n) ,其中 n 是数组大小。

思路

对堆的使用还是很陌生的,当了一把调库高手。。。。好好复习二叉树

  • 用字典统计每个元素的数量
  • 遍历字典,然后分成k堆,当堆的数量=k+1时,则把数量最小的对弹出,遍历结束剩下的k个堆即为所求

代码

import heapq


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

    示例 1:
    输入: nums = [1,1,1,2,2,3], k = 2
    输出: [1,2]

    示例 2:
    输入: nums = [1], k = 1
    输出: [1]

    提示:
    1 <= nums.length <= 105
    k 的取值范围是 [1, 数组中不相同的元素的个数]
    题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的

    进阶:你所设计算法的时间复杂度 必须 优于 O(n log n) ,其中 n 是数组大小。
    """

    def topKFrequent(self, nums, k):
        re = {}
        for i in nums:
            re[i] = re.get(i, 0) + 1
        por = []
        result = []

        for key,valus in re.items():
            heapq.heappush(por, (valus, key))
            if len(por) > k:
                heapq.heappop(por)

        for i in por:
            result.append(i[1])

        return result


if __name__ == '__main__':
    nums = [[1, 1, 1, 2, 2, 3], [1]]
    k = [2, 1]
    test = Solution()
    for i in range(len(nums)):
        print(test.topKFrequent(nums[i], k[i]))

总结

现在你的气质里,藏着你写过的BUG,挠过的头和掉过的头发

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值