当前位置: 首页 > news >正文

免费网站制作模板网络推广和信息流优化一样么

免费网站制作模板,网络推广和信息流优化一样么,在线制作表情包生成器软件,做网站找外包公司要要搞清楚什么代码随想录算法训练营第十天 | 239.滑动窗口最大值、347.前K个高频元素 文章目录 代码随想录算法训练营第十天 | 239.滑动窗口最大值、347.前K个高频元素1 LeetCode 239.滑动窗口最大值2 LeetCode 347.前K个高频元素 1 LeetCode 239.滑动窗口最大值 题目链接:https…

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

文章目录

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

1 LeetCode 239.滑动窗口最大值

题目链接:https://leetcode.cn/problems/sliding-window-maximum/description/

给你一个整数数组 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       31 [3  -1  -3] 5  3  6  7       31  3 [-1  -3  5] 3  6  7       51  3  -1 [-3  5  3] 6  7       51  3  -1  -3 [5  3  6] 7       61  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 = [1,3,-1,-3,5,3,6,7], k = 3,刚开始排序[3,1,-1],没问题,最大值在队头,然后我们还需要向右移动,然后弹出1,可是优先级队列中1在队列的中间,无法弹出,所以就无法实现找滑动窗口中的最大值。

我们可以利用双端队列来构造一个单调队列来解决这道题目。

  • 创建一个双端队列(Deque)来存储元素的索引,而不是存储元素的值,这是因为我们需要在队列中比较索引,以确定元素是否在窗口内,创建一个空列表 result 来存储最终的结果。
  • 我们开始遍历数组 nums,逐个处理每个元素。
  • 在每次遍历之前,检查队列的首元素是否已经超出了当前窗口的范围,如果队列的首元素对应的索引小于当前索引减去窗口大小 k 加 1,就将队列的首元素弹出(出队),因为它不再在窗口内。
  • 继续检查队列中的元素,如果队列中的元素对应的数组值小于等于当前元素的值,将它们从队列的尾部弹出,因为它们不可能是窗口内的最大值,我们的目标是确保队列中的元素是按照递减顺序排列的,以便窗口内的最大值总是在队列的首元素位置。
  • 将当前元素的索引添加到队列的尾部。
  • 当我们遍历到达满足窗口大小的位置(即当前索引大于等于 k-1),就可以获取窗口内的最大值。这是因为我们确保队列的首元素是当前窗口内的最大值的索引。将队列的首元素对应的值添加到结果列表 result 中。
  • 继续遍历整个数组,重复上述步骤直到遍历完成。
  • 最后返回结果列表 result,其中包含了每个窗口内的最大值。

思路清楚,下面我们来写一下代码:

(1)Python版本代码

from collections import deque
class Solution:def maxSlidingWindow(self, nums, k):result = [] # 用于存储最终的滑动窗口最大值window = deque()    # 创建一个双端队列用于存储窗口内的元素索引n = len(nums)for i in range(n):      if window and window[0] < i - k + 1:    # 移除队列中超出窗口范围的索引window.popleft()while window and nums[i] >= nums[window[-1]]:   # 移除队列中比当前元素小的元素索引window.pop()window.append(i)    # 将当前元素的索引加入队列if i >= k - 1:  # 当窗口形成后,将队列的首元素对应的值加入结果列表result.append(nums[window[0]])return result

下面是代码随想录中的代码:

from collections import dequeclass MyQueue: #单调队列(从大到小def __init__(self):self.queue = deque() #这里需要使用deque实现单调队列,直接使用list会超时#每次弹出的时候,比较当前要弹出的数值是否等于队列出口元素的数值,如果相等则弹出。#同时pop之前判断队列当前是否为空。def pop(self, value):if self.queue and value == self.queue[0]:self.queue.popleft()#list.pop()时间复杂度为O(n),这里需要使用collections.deque()#如果push的数值大于入口元素的数值,那么就将队列后端的数值弹出,直到push的数值小于等于队列入口元素的数值为止。#这样就保持了队列里的数值是单调从大到小的了。def push(self, value):while self.queue and value > self.queue[-1]:self.queue.pop()self.queue.append(value)#查询当前队列里的最大值 直接返回队列前端也就是front就可以了。def front(self):return self.queue[0]class Solution:def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:que = MyQueue()result = []for i in range(k): #先将前k的元素放进队列que.push(nums[i])result.append(que.front()) #result 记录前k的元素的最大值for i in range(k, len(nums)):que.pop(nums[i - k]) #滑动窗口移除最前面元素que.push(nums[i]) #滑动窗口前加入最后面的元素result.append(que.front()) #记录对应的最大值return result

(2)C++版本代码

#include <vector>
#include <deque>class Solution {
public:std::vector<int> maxSlidingWindow(std::vector<int>& nums, int k) {std::vector<int> result;std::deque<int> window;int n = nums.size();for (int i = 0; i < n; ++i) {// 移除队列中超出窗口范围的索引if (!window.empty() && window.front() < i - k + 1) {window.pop_front();}// 移除队列中比当前元素小的元素索引while (!window.empty() && nums[i] >= nums[window.back()]) {window.pop_back();}// 将当前元素的索引加入队列window.push_back(i);// 当窗口形成后,将队列的首元素对应的值加入结果列表if (i >= k - 1) {result.push_back(nums[window.front()]);}}return result;}
};
  • 时间复杂度: O(n)
  • 空间复杂度: O(k)

后续研究了一下,发现这题可以用优先队列实现的,也就是用大根堆实现,下面直接给出我学到的代码,感兴趣的朋友可以研究一下:

#include <vector>
#include <queue>
#include <utility>class Solution {
public:std::vector<int> maxSlidingWindow(std::vector<int>& nums, int k) {std::vector<int> result;std::priority_queue<std::pair<int, int>> pq; // 存储元素值和索引的大根堆for (int i = 0; i < nums.size(); ++i) {while (!pq.empty() && pq.top().second <= i - k) {pq.pop(); // 移除不在窗口内的元素}pq.push({nums[i], i});if (i >= k - 1) {result.push_back(pq.top().first); // 将窗口的最大值加入结果列表}}return result;}
};

此时的时间复杂度到达了O(log k)。

2 LeetCode 347.前K个高频元素

题目链接:https://leetcode.cn/problems/top-k-frequent-elements/description/

给你一个整数数组 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个元素,我们就要想到map和堆的结合运用,其中map很适合用来统计元素频率,然后堆也很适合维系一个单调的K个元素的排序集合,然后对数据集不断地遍历,不断地更新维系地集合。

堆有两种形式,一种是大顶堆(也叫大根堆),另一种是小顶堆(也叫小根堆),相信学过408的朋友对堆这种数据结构应该不陌生,那么在本题中我们应该选择哪一种形式的堆呢?答案是小顶堆,为什么?因为如果选择大顶堆,那么我们在每次加入元素之后,判断堆中元素是否超过K个(因为我们只需要维系K个元素即可),如果超过我们就需要将堆顶元素弹出,但是大顶堆的话此时堆顶元素是最大值,最后遍历完我们其实收集的是前K个低频元素,刚好相反了,因此我们就需要选择小顶堆来实现(可以手动画图感受一下,堆也就是一颗完全二叉树)。

(1)Python版本代码

import heapqclass Solution:def topKFrequent(self, nums, k):# 统计每个元素的频率hashmap = {}for num in nums:hashmap[num] = hashmap.get(num, 0) + 1# 使用最小堆来存储所有元素heap = []for key, value in hashmap.items():heapq.heappush(heap, (value, key))  # 存储频率和元素# 弹出除了频率最高的k个元素之外的所有元素while len(heap) > k:heapq.heappop(heap)# 提取结果return [key for _, key in heap]if __name__ == '__main__':s = Solution()nums = list(map(int, input().split()))k = int(input())print(s.topKFrequent(nums, k))

(2)C++版本代码

#include <iostream>
#include <vector>
#include <queue>
#include <unordered_map>
#include <utility>
#include <functional>class Solution {
public:std::vector<int> topKFrequent(std::vector<int>& nums, int k) {// 统计每个元素的频率std::unordered_map<int, int> hashmap;for (int num : nums) {++hashmap[num];}// 使用最小堆来存储所有元素std::priority_queue<std::pair<int, int>, std::vector<std::pair<int, int>>, std::greater<std::pair<int, int>>> heap;for (auto& it : hashmap) {heap.push({it.second, it.first});if (heap.size() > k) {heap.pop();}}std::vector<int> result;while (!heap.empty()) {result.push_back(heap.top().second);heap.pop();}return result;}
};int main() {Solution s;std::vector<int> nums;int num;while (std::cin >> num) {nums.push_back(num);if (std::cin.peek() == '\n') break;}int k;std::cin >> k;std::vector<int> result = s.topKFrequent(nums, k);for (int i : result) {std::cout << i << " ";}std::cout << std::endl;return 0;
}
  • 时间复杂度:O(nlogn)
  • 空间复杂度:O(n)
http://www.ysxn.cn/news/3659.html

相关文章:

  • 武汉做网站找哪家海南乐秀同城群软件下载
  • 给网站做备案谷歌外贸平台
  • 想做个赚钱的网站不知道做那种2023广东最新疫情
  • 网站服务器的作用在哪里打广告效果最好
  • 网站返回顶部怎么做网页设计友情链接怎么做
  • 帝国cms影视网站模板免费com域名申请注册
  • 做网站的好框架2024免费网站推广大全
  • 网站前台怎么套用织梦后台品牌广告投放
  • wordpress屏蔽右键菜单并提示宁波seo推广优化
  • 做网站的一定要开80或8080端口品牌广告和效果广告的区别
  • 衡水做网站设计外贸建站优化
  • 成都网站建设优创智汇矿坛器材友情交换
  • 医疗网站建设计划书淘宝seo对什么内容优化
  • 双语教学示范课程建设项目网站口碑营销例子
  • 佳木斯城乡建设局网站杭州小周seo
  • web前端如何仿网站seo网站营销推广公司
  • 建设网站利用点击量赚钱互联网营销师报名费
  • 什么网站可以免费做视频的软件下载百度关键词指数
  • 怎么给新公司做网站seo自动推广工具
  • 凡科网站制作教程百度推广助手app下载
  • 邢台如何做企业网站b2b外贸接单平台
  • 网站如何做会员通用德州seo优化
  • 网站建设营销外包公司排名移动营销
  • 网络商品推广策划书优化关键词的方法正确的是
  • 什么是sem营销seo排名优化首页
  • 网站更换服务器如何做镜像浏览器直接进入网站的注意事项
  • 2017民非单位年检那个网站做谷歌seo排名技巧
  • 家居企业网站建设流程电商培训学校
  • 什么软件是做网站模板的短视频精准获客
  • 长沙专业网站建设公司竞价排名营销