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

算法题 最大频率栈

最大频率栈

问题描述

实现FreqStack类,模拟一个最大频率栈(频率栈)。

FreqStack有两个方法:

  • push(int val):将整数val推入栈中
  • pop()移除并返回栈中频率最高的元素
    • 如果有多个元素频率相同,返回最接近栈顶的元素

示例

FreqStackfreqStack=newFreqStack();freqStack.push(5);// 栈为 [5]freqStack.push(7);// 栈为 [5,7]freqStack.push(5);// 栈为 [5,7,5]freqStack.push(7);// 栈为 [5,7,5,7]freqStack.push(4);// 栈为 [5,7,5,7,4]freqStack.push(5);// 栈为 [5,7,5,7,4,5]freqStack.pop();// 返回 5,因为 5 的频率最高freqStack.pop();// 返回 7,5 和 7 频率相同(2),7 更接近栈顶freqStack.pop();// 返回 5freqStack.pop();// 返回 4

算法思路

多层栈 + 频率映射

  1. 核心数据结构

    • freq:哈希表,记录每个元素的当前频率
    • group:哈希表,group[f]存储所有频率为f的元素栈
    • maxFreq:记录当前最大频率
  2. push 操作

    • 更新元素频率:freq[val]++
    • 将元素推入对应频率的栈:group[freq[val]].push(val)
    • 更新最大频率:maxFreq = max(maxFreq, freq[val])
  3. pop 操作

    • group[maxFreq]弹出栈顶元素
    • 减少该元素的频率:freq[val]--
    • 如果group[maxFreq]为空,maxFreq--

代码实现

方法一:多层栈

importjava.util.*;classFreqStack{/** * 最大频率栈的实现 * * 核心数据结构: * - freq: 元素 -> 频率 * - group: 频率 -> 元素栈(存储该频率的所有元素) * - maxFreq: 当前最大频率 */privateMap<Integer,Integer>freq;// 元素频率映射privateMap<Integer,Deque<Integer>>group;// 频率分组栈privateintmaxFreq;// 当前最大频率publicFreqStack(){freq=newHashMap<>();group=newHashMap<>();maxFreq=0;}/** * 推入元素到频率栈 * * 时间复杂度: O(1) * * @param val 要推入的元素 */publicvoidpush(intval){// 更新元素频率intf=freq.getOrDefault(val,0)+1;freq.put(val,f);// 更新最大频率maxFreq=Math.max(maxFreq,f);// 将元素推入对应频率的栈group.computeIfAbsent(f,k->newArrayDeque<>()).push(val);}/** * 弹出频率最高且最接近栈顶的元素 * * 时间复杂度: O(1) * * @return 弹出的元素 */publicintpop(){// 从最大频率栈中弹出元素intval=group.get(maxFreq).pop();// 减少该元素的频率freq.put(val,freq.get(val)-1);// 如果当前最大频率的栈为空,减少最大频率if(group.get(maxFreq).isEmpty()){maxFreq--;}returnval;}}

算法分析

  • 时间复杂度:O(1)

    • 哈希表操作:O(1)
    • 栈操作:O(1)
    • 频率更新:O(1)
  • 空间复杂度:O(N)

    • N 是推入的元素总数
    • freq映射:O(不同元素数量)
    • group映射:O(N),因为每个推入的元素都在某个频率栈中
  • 正确性

    • 频率优先:总是从最大频率栈中弹出
    • 栈顶优先:同一频率的元素按推入顺序存储,后推入的在栈顶
    • 频率维护:pop 后正确更新元素频率和最大频率

算法过程

操作序列: push(5), push(7), push(5), push(7), push(4), push(5) 状态变化: push(5): - freq: {5:1} - group: {1: [5]} - maxFreq: 1 push(7): - freq: {5:1, 7:1} - group: {1: [7,5]} - maxFreq: 1 push(5): - freq: {5:2, 7:1} - group: {1: [7,5], 2: [5]} - maxFreq: 2 push(7): - freq: {5:2, 7:2} - group: {1: [7,5], 2: [7,5]} - maxFreq: 2 push(4): - freq: {5:2, 7:2, 4:1} - group: {1: [4,7,5], 2: [7,5]} - maxFreq: 2 push(5): - freq: {5:3, 7:2, 4:1} - group: {1: [4,7,5], 2: [7,5], 3: [5]} - maxFreq: 3 pop() → 5: - 从group[3]弹出5 - freq: {5:2, 7:2, 4:1} - group: {1: [4,7,5], 2: [7,5], 3: []} - maxFreq: 2 (因为group[3]为空) pop() → 7: - 从group[2]弹出7 - freq: {5:2, 7:1, 4:1} - group: {1: [4,7,5], 2: [5], 3: []} - maxFreq: 2 pop() → 5: - 从group[2]弹出5 - freq: {5:1, 7:1, 4:1} - group: {1: [4,7,5], 2: [], 3: []} - maxFreq: 1 (因为group[2]为空) pop() → 4: - 从group[1]弹出4 - freq: {5:1, 7:1, 4:0} - group: {1: [7,5], 2: [], 3: []} - maxFreq: 1

测试用例

importjava.util.*;publicclassTest{publicstaticvoidmain(String[]args){// 测试用例1:标准示例FreqStackfreqStack1=newFreqStack();freqStack1.push(5);freqStack1.push(7);freqStack1.push(5);freqStack1.push(7);freqStack1.push(4);freqStack1.push(5);System.out.println("Test 1:");System.out.println("pop1: "+freqStack1.pop());// 5System.out.println("pop2: "+freqStack1.pop());// 7System.out.println("pop3: "+freqStack1.pop());// 5System.out.println("pop4: "+freqStack1.pop());// 4// 测试用例2:单个元素FreqStackfreqStack2=newFreqStack();freqStack2.push(1);freqStack2.push(1);System.out.println("Test 2:");System.out.println("pop1: "+freqStack2.pop());// 1System.out.println("pop2: "+freqStack2.pop());// 1// 测试用例3:不同元素FreqStackfreqStack3=newFreqStack();freqStack3.push(1);freqStack3.push(2);freqStack3.push(3);System.out.println("Test 3:");System.out.println("pop1: "+freqStack3.pop());// 3System.out.println("pop2: "+freqStack3.pop());// 2System.out.println("pop3: "+freqStack3.pop());// 1// 测试用例4:复杂频率变化FreqStackfreqStack4=newFreqStack();freqStack4.push(1);freqStack4.push(2);freqStack4.push(1);freqStack4.push(3);freqStack4.push(2);freqStack4.push(1);System.out.println("Test 4:");System.out.println("pop1: "+freqStack4.pop());// 1 (freq=3)System.out.println("pop2: "+freqStack4.pop());// 2 (freq=2, more recent than 1)System.out.println("pop3: "+freqStack4.pop());// 1 (freq=2)System.out.println("pop4: "+freqStack4.pop());// 3 (freq=1)System.out.println("pop5: "+freqStack4.pop());// 2 (freq=1)System.out.println("pop6: "+freqStack4.pop());// 1 (freq=1)// 测试用例5:大量操作FreqStackfreqStack5=newFreqStack();for(inti=0;i<1000;i++){freqStack5.push(i%10);}// 测试用例6:边界值FreqStackfreqStack6=newFreqStack();freqStack6.push(Integer.MAX_VALUE);freqStack6.push(Integer.MIN_VALUE);freqStack6.push(Integer.MAX_VALUE);System.out.println("Test 6:");System.out.println("pop1: "+freqStack6.pop());// MAX_VALUESystem.out.println("pop2: "+freqStack6.pop());// MIN_VALUESystem.out.println("pop3: "+freqStack6.pop());// MAX_VALUE}}

关键点

  1. 数据结构

    • 使用DequeStack作为频率分组的容器
    • ArrayDequeStack更高效(避免同步开销)
  2. 频率维护

    • push 时增加频率并更新最大频率
    • pop 时减少频率并在必要时减少最大频率
  3. 栈顶优先

    • 同一频率的元素按推入顺序存储
    • 后推入的元素在栈顶,pop 时优先返回
  4. 空间效率

    • 每个推入的元素只存储一次
    • 频率映射只存储不同元素的频率

常见问题

  1. 为什么不用优先队列?
    • 优先队列无法高效处理频率动态变化的情况
    • 需要 O(log n) 时间更新优先级
    • 多层栈提供 O(1) 时间复杂度
http://www.cnnetsun.cn/news/483967.html

相关文章:

  • 知识管理工具又添新锐,notion vs sward一文对比解析
  • 当PLC遇上灌装线:手把手拆解产线控制逻辑
  • 无人驾驶车辆模型基于RLS算法预测控制侧偏刚度估算,递归最小二乘法在线识别前后轮胎侧偏刚度及大...
  • 学霸同款2026 AI论文写作软件TOP9:本科生毕业论文必备测评
  • 优雅的处理 API 接口敏感数据加解密(方案详解)
  • 《Light: Science Applications》超表面偏振态与偏振度完全独立控制新范式
  • Qwen3Guard-Gen-8B可用于简历生成内容真实性核查
  • Glitch项目内容审核:Qwen3Guard-Gen-8B保护开发者社区生态
  • Java程序员如何备战金三银四?
  • 三菱FX5U七轴标准程序解析
  • 收藏!小白程序员必看:大语言模型核心原理全解析(从ChatGPT到Transformer)
  • 2.34 二手车价格预测完整案例:特征工程、模型训练、调参全流程
  • 2.46 AI大赛实战:资金流入流出预测,从数据到模型完整解决方案
  • AI Agent正在消灭编程岗位?真相是:这是程序员的最好时代!小白开发者如何抓住这波AI红利?
  • 【深度干货】AI Agent的“六神合体“术:从感知到优化的完整闭环,小白也能懂
  • 中国团队打造音乐MV制作新利器:让任何人都能拍出专业级音乐视频
  • 2.36 模型融合原理与技巧:Stacking、Blending,提升模型效果的最后一步
  • MATLAB海洋声传播仿真设计与实现
  • 性能测试数据生成实用指南
  • AI智慧司牧服务系统:打造草原上的“千里眼”与“数字牧羊人”
  • 基于拥挤距离的多目标粒子群优化算法(MO-PSO-CD)详解
  • 类型断言:强制类型转换的技巧
  • AG 的“石器时代”结束了!读 PDF 别再瞎折腾工具链,RAG-Anything + Milvus 一招制胜!
  • 从“提示词奴隶“到“AI架构师“:Anthropic上下文工程大揭秘,小白也能驯服大模型!
  • 【Linux命令大全】003.文档编辑之pico命令(实操篇)
  • 基于STM32的运动信息检测装置设计与实现
  • 无人值守智能污水处理控制系统:威纶通触摸屏与西门子PLC协同运行,真实工程项目稳定运行一年多供...
  • 今日头条视频下载方法汇总 高清无水印 (2026 最新实测)
  • 2026全新版Java面试八股文.pdf出炉, 简直把所有 Java 知识面试题写出来了
  • 硕士论文过审第一步:paperzz 论文查重功能,怎么帮你避开重复率雷区?