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

代码随想录系列

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,挠过的头和掉过的头发

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
根据引用\[1\],可以使用暴力解法来求解滑动窗口最大值。具体的做法是,遍历数组,对于每个窗口,使用一个内部循环来找到窗口中的最大值,并将其存储在结果数组中。时间复杂度为O(n*k),其中n为数组长度,k为窗口大小。 根据引用\[2\],还可以使用队列来求解滑动窗口最大值。具体的做法是,使用一个双端队列来维护一个单调递减的窗口。遍历数组,对于每个元素,首先判断队头是否在滑动窗口范围内,如果不在,则将其从队头移除。然后,将当元素与队尾元素比较,如果当元素大于队尾元素,则将队尾元素移除,直到队列为空或者当元素小于等于队尾元素。最后,将当元素的索引插入队尾。如果滑动窗口元素个数达到了k个,并且始终维持在窗口中,就将队头元素加入答案数组中。时间复杂度为O(n),其中n为数组长度。 综上所述,可以使用暴力解法或者使用队列来求解leetcode滑动窗口最大值。 #### 引用[.reference_title] - *1* *3* [leetcode239. 滑动窗口最大值](https://blog.csdn.net/kkkkuuga/article/details/124829581)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Leetcode#239. 滑动窗口最大值 (Java解法)](https://blog.csdn.net/paranior/article/details/114890555)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值