day12 347.前 K 个高频元素239. 滑动窗口最大值

news/2025/1/27 7:00:25/文章来源:https://www.cnblogs.com/lin0304/p/18691448
  1. topKFrequent 方法:返回出现频率前 k 高的元素
    这个方法通过以下步骤实现:
    统计频率:
    使用 HashMap 统计每个元素的出现频率。
    时间复杂度:O(n),其中 n 是数组的长度。
    优先级队列(最大堆):
    使用优先级队列(PriorityQueue)来存储频率信息,队列按照频率降序排列。
    将所有元素及其频率加入优先级队列。
    时间复杂度:每次插入操作为 O(logn),总时间复杂度为 O(nlogn)。
    提取结果:
    从优先级队列中依次提取 k 个元素,存入结果数组。
    时间复杂度:每次提取操作为 O(logn),总时间复杂度为 O(klogn)。
    代码分析
    效率:虽然优先级队列的实现比直接排序的方法效率高,但总体时间复杂度仍然为 O(nlogn)。
    优点:代码简洁,利用了 Java 的内置数据结构,易于理解和实现。
    改进:如果需要进一步优化,可以考虑使用桶排序,将时间复杂度降低到 O(n)。

//请你返回其中出现频率前 k 高的元素
public int[] topKFrequent(int[] nums, int k) {
Map<Integer, Integer> map = new HashMap<>();
int[] res = new int[k];
for (int i = 0; i < nums.length; i++) {
map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);
}
//虽然也可以选择集合实现,但相对来说优先级队列效率更高
PriorityQueue<Map.Entry<Integer, Integer>> pq = new PriorityQueue<>(new Comparator<Map.Entry<Integer, Integer>>() {
@Override
public int compare(Map.Entry<Integer, Integer> o1, Map.Entry<Integer, Integer> o2) {
return o2.getValue() - o1.getValue();
}
});
for (Map.Entry<Integer, Integer> en : map.entrySet()) {
pq.offer(en);
}
for (int i = 0; i < res.length; i++) {
res[i]=pq.poll().getKey();
}
/List<Map.Entry<Integer, Integer>> list = new ArrayList<>(map.entrySet());
list.sort(Map.Entry.comparingByValue(Comparator.reverseOrder()));
for (int i = 0; i < k; i++) {
res[i] = list.get(i).getKey();
}
/
return res;
}

  1. maxSlidingWindow 方法:滑动窗口最大值
    这个方法实现了两种实现方式:
    方法 1:使用自定义的单调队列 ProseQueue
    单调队列的实现:
    使用 ArrayDeque 来维护一个单调递减的队列。
    每次插入新元素时,移除队列中所有小于当前元素的值,以保持单调性。
    时间复杂度:每次插入操作为 O(1)(平均情况下),总时间复杂度为 O(n)。
    滑动窗口的逻辑:
    在窗口滑动时,移除超出窗口范围的元素。
    记录当前窗口的最大值(队头元素)。
    时间复杂度:O(n)。
    方法 2:直接使用 ArrayDeque 实现单调队列
    直接使用双端队列:
    在窗口滑动时,直接在 ArrayDeque 中维护单调递减的队列。
    移除超出窗口范围的元素和小于当前元素的值。
    时间复杂度:O(n)。
    效率对比:
    方法 1 使用了自定义的 ProseQueue 类,代码更加模块化,但效率略低(38ms)。
    方法 2 直接使用 ArrayDeque,减少了类的封装,效率更高(26ms)。
    代码分析
    效率:两种方法的时间复杂度均为 O(n),但直接使用 ArrayDeque 的方法效率更高。
    优点:直接使用 ArrayDeque 的方法减少了类的封装,代码更加简洁。

  2. 辅助类 ProseQueue
    这个类封装了单调队列的逻辑,提供了以下方法:
    offer:插入新元素,保持单调递减。
    poll:移除指定值,如果队头元素等于该值。
    getMax:获取当前队头元素(最大值)。
    代码分析
    效率:单调队列的实现非常高效,时间复杂度为 O(n)。
    优点:封装了单调队列的逻辑,代码更加模块化,易于复用。

    //239. 滑动窗口最大值
    public int[] maxSlidingWindow(int[] nums, int k) {
    //另外定义一个单调队列实现,效率较低38ms
    /ProseQueue proseQueue = new ProseQueue();
    int[] result = new int[nums.length - k + 1];
    for (int i = 0; i < k-1; i++) {
    proseQueue.offer(nums[i]);
    }
    for (int i = k-1,j=0; i < nums.length; i++) {
    proseQueue.offer(nums[i]);
    result[j]=proseQueue.getMax();
    proseQueue.poll(nums[j++]);
    }
    return result;
    /
    //不用另外定义一个单调队列,直接利用双端队列实现对应思想即可26ms
    ArrayDeque deque = new ArrayDeque<>();
    int[] result = new int[nums.length - k + 1];
    for (int i = 0; i < nums.length; i++) {
    if (i>=k){
    if(nums[i-k]deque.peekFirst())deque.pollFirst();
    }
    while (!deque.isEmpty() && nums[i] > deque.getLast()) {
    deque.removeLast();
    }
    deque.addLast(nums[i]);
    if (i>=k-1){
    result[i-k+1] = deque.peekFirst();
    }
    }
    return result;
    }
    //239. 滑动窗口最大值 辅助类 单调队列
    class ProseQueue{
    Deque deque = new ArrayDeque<>();
    public ProseQueue() {}
    public void offer(int x){
    while (!deque.isEmpty()&&deque.getLast()<x){
    deque.removeLast();
    }
    deque.offerLast(x);
    }
    public int poll(int val){
    if(!deque.isEmpty()&&deque.peekFirst()
    val){
    return deque.pollFirst();
    }
    return val;
    }
    public int getMax(){
    return deque.peekFirst();
    }
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/875812.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深入探讨数据库索引类型:B-tree、Hash、GIN与GiST的对比与应用

title: 深入探讨数据库索引类型:B-tree、Hash、GIN与GiST的对比与应用 date: 2025/1/26 updated: 2025/1/26 author: cmdragon excerpt: 在现代数据库管理系统中,索引技术是提高查询性能的重要手段。当数据量不断增长时,如何快速、有效地访问这些数据成为了数据库设计的核…

玩转单例模式

Java中单例(Singleton)模式是一种广泛使用的设计模式。单例模式的主要作用是保证在Java程序中,某个类只有一个实例存在。一些管理器和控制器常被设计成单例模式。 单例模式的好处:能够避免实例对象的重复创建,不仅可以减少每次创建对象的时间开销,还可以节约内存空间; 能够…

佳能EOS888说明书

这回讲佳能EOS888,EOS 888/EOS 5000于1995年元月推出,原来主要是面向东南亚市场,“888”就是取“发发发”的谐音。后来受到用户喜爱,于是就以EOS 5000的型号推向国际市场。 先贴个规格参数由于某文库某丁网某人的说明书需要付费下载,并且缺39页,找了英文版的39页补全。 说…

处理nginx解析跳转的域名不是最新的ip问题

我的场景是这样的,使用了贝锐的ddns服务,但是服务器上的nginx配置的域名解析不到最新的ip地址 问题如下我的贝锐域名可以打开,但是这里显示的不是最新的ip地址 在nginx.conf配置文件中加入resolver 223.5.5.5 223.6.6.6 valid=60s; 这里表示缓存的时间是60秒

【模拟电子技术】15-Q点稳定的放大电路和基本共集放大电路

【模拟电子技术】15-Q点稳定的放大电路和基本共集放大电路增加RE抑制温漂增加RB2并使得经过它的电流很大,分压大,使得静态工作点趋于稳定但是RE电阻在交流通路中会使得放大倍数减小(即使我们分析输入电阻,得到输入电阻增加了,但是我们还是希望得到一个高放大倍数的电路)于…

【AI+零售】构建一个有智能体参与的去中心化RWA零售生态系统商业模型

# 零售行业 在零售行业中,传统中心化模式因信息不对称、效率低下和利益分配不公平等问题逐渐暴露其局限性。而随着区块链、人工智能(AI)和智能体(Agent)技术的发展,去中心化零售生态系统成为可能。本文将系统性地探讨如何构建一个有智能体深度参与的去中心化零售商业模型…

《CPython Internals》阅读笔记:p356-p359

《CPython Internals》学习第 19天,p356-p359 总结,总计 4 页。 一、技术总结 1.benchmark suite The benchmark suite is the tool to use when comparing the complete performance of Python. The Python Benchmark suite is a collection of Python applications design…

昆工昆明理工大学材料25调剂名额

--材测材料物理与化学材料学材料表征与分析材料工程F001现代材料测试技术F002材料成型技术基础864材料科学基础

@FeignClient中configuration属性的简单介绍

第一个控制请求的日志打印级别 先看效果图 日志级别配置方式新增类 public class FeignConfig {/*** NONE【性能最佳,适用于生产】:不记录任何日志(默认值)* BASIC【适用于生产环境追踪问题】:仅记录请求方法、URL、响应状态代码以及执行时间* HEADERS:记录BASIC级别的基…

【MySQL】Mysql 加锁机制与死锁分析

一、锁的分类1.1 锁模式1.2 锁粒度1.2.1 全局锁1.2.2 表级锁1.2.3 页级锁1.2.4 行锁1.3 锁范围1.3.1 记录锁1.3.2 间隙锁(Gap)1.3.3 临键锁1.3.4 意向锁(IS、IX)1.4 兼容性二、加锁机制2.1 加锁规则2.2 加锁分析2.2.1 无索引等值查询2.2.2 无索引范围查询2.2.3 无索引未命中…

Linux上安装DVWA,小白也能上手

dvwa是什么? dvwa全称是Damn Vulnerable Web Application,自己翻译吧。 它是一款非常实用的Web应用安全学习和测试平台。那我就在linux上安装下看看。 对了,我这里的linux是centos 7。 首先,dvwa需要什么? 1、数据库:mysql 2、web服务器:我这里选的是apache,而且php还要…

关于pushup与pushdown的几种常见情况

适用于线段树、平衡树等树形结构。 一.区间修改,区间求和(求最值) 二.最大连续子序列 这里有一种类似于 \(DP\) 的方法。 对于一个节点 \(Rt\),我们需要维护四个值。\(sum\) : 此区间的总和。 \(lmx\) : 此区间从左边开头的最大连续子序列。 \(rmx\) : 此区间从右边开头的最…