Implement `FreqStack`, a class which simulates the operation of a stack-like data structure.

FreqStack has two functions:

  • push(int x), which pushes an integer xonto the stack.
  • pop(), which removes and returns the most frequent element in the stack.
    • If there is a tie for most frequent element, the element closest to the top of the stack is removed and returned.

Example 1:

Input:
["FreqStack","push","push","push","push","push","push","pop","pop","pop","pop"],
[[],[5],[7],[5],[7],[4],[5],[],[],[],[]]
Output: [null,null,null,null,null,null,null,5,7,5,4]
Explanation:
After making six .push operations, the stack is [5,7,5,7,4,5] from bottom to top. Then: pop() -> returns 5, as 5 is the most frequent.
The stack becomes [5,7,5,7,4]. pop() -> returns 7, as 5 and 7 is the most frequent, but 7 is closest to the top.
The stack becomes [5,7,5,4]. pop() -> returns 5.
The stack becomes [5,7,4]. pop() -> returns 4.
The stack becomes [5,7].

Note:

  • Calls to FreqStack.push(int x) will be such that 0 <= x <= 10^9.
  • It is guaranteed that FreqStack.pop() won't be called if the stack has zero elements.
  • The total number of FreqStack.push calls will not exceed 10000 in a single test case.
  • The total number of FreqStack.pop calls will not exceed 10000 in a single test case.
  • The total number of FreqStack.push and FreqStack.pop calls will not exceed 150000across all test cases.

这道题让我们实现一种最大频率栈,有入栈和出栈功能,需要每次出栈的都是栈中出现频率最大的数字,若有多个数字的频率相同,那么离栈顶最近的元素先出栈。刚开始看到这道题的时候,博主立马联想到了 [LRU Cache](http://www.cnblogs.com/grandyang/p/4587511.html) 和 [LFU Cache](http://www.cnblogs.com/grandyang/p/6258459.html),想着会不会也需要在迭代器上做文章,但实际是我想多了,虽然同为 Hard 的题目,这道题的解法却要比之前那两道要简单的多。这里只跟数字出现的频率有关,只有在频率相等的情况下才会考虑栈的后入先出的特性,所以一定是需要统计栈中每个数字出现的频率的,我们使用一个 HashMap 来建立每个数字跟其出现次数之间的映射。由于频率相等的数字可能有多个,所以我们必须知道某个特性频率下都有哪些数字,再用一个 HashMap 来建立频率和该频率下所有的数字之间的映射,可以将这些数组放到一个数组或者一个栈中,这里为了简便起见,就使用一个数组了。另外,我们还需要维护一个当前最大频率的变量,可以通过这个值到 HashMap 中快速定位数组的位置。好,一切准备就绪之后就开始解题吧,对于入栈函数 push(),首先需要将x对应的映射值加1,并更新最大频率 mxFreq,然后就是要把x加入当前频率对应的数组中,注意若某个数字出现了3次,那么数字会分别加入频率为 1,2,3 的映射数组中。接下来看出栈函数 pop() 如何实现,由于我们知道当前最大频率 mxFreq,就可以直接去 HashMap 中取出该频率下的所有数字的数组,题目说了若频率相等,取离栈顶最近的元素,这里就是数组末尾的数组,取到之后,要将该数字从数组末尾移除。移除之后,我们要检测一下,若数组此时为空了,说明当前最大频率下之后一个数字,取出之后,最大频率就要自减1,还有不要忘记的就是取出数字的自身的频率值也要自减1,参见代码如下:


解法一:

class FreqStack {
public:
FreqStack() {} void push(int x) {
mxFreq = max(mxFreq, ++freq[x]);
m[freq[x]].push_back(x);
} int pop() {
int x = m[mxFreq].back();
m[mxFreq].pop_back();
if (m[freq[x]--].empty()) --mxFreq;
return x;
} private:
int mxFreq;
unordered_map<int, int> freq;
unordered_map<int, vector<int>> m;
};

我们还可以使用 multimap 来建立频率和数字之间的映射,利用其可重复的特性,那么同一个频率就可以映射多个数字了。同时,由于 multimap 默认是按从小到大排序的,而我们希望按频率从大到小排序,所以加上一个参数使其改变排序方式。在入栈函数中,将x的频率自增1,然后跟x组成 pair 对儿加入 multimap 中。在出栈函数中,由于其是按从大到小排序的,而且后进的排在前面,那么第一个映射对儿就是频率最大且最后加入的数字,将其取出并从 multimap 中移除,并同时将该数字的映射频率值减1即可,参见代码如下:


解法二:

class FreqStack {
public:
FreqStack() {} void push(int x) {
m.insert({++freq[x], x});
} int pop() {
int x = m.begin()->second;
m.erase(m.begin());
--freq[x];
return x;
} private:
unordered_map<int, int> freq;
multimap<int, int, greater_equal<int>> m;
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/895

参考资料:

https://leetcode.com/problems/maximum-frequency-stack/

https://leetcode.com/problems/maximum-frequency-stack/discuss/163410/C%2B%2BJavaPython-O(1)

https://leetcode.com/problems/maximum-frequency-stack/discuss/229638/C%2B%2B-multimap-solution-132-ms

https://leetcode.com/problems/maximum-frequency-stack/discuss/163453/JAVA-O(1)-solution-easy-understand-using-bucket-sort

[LeetCode All in One 题目讲解汇总(持续更新中...)](https://www.cnblogs.com/grandyang/p/4606334.html)

[LeetCode] 895. Maximum Frequency Stack 最大频率栈的更多相关文章

  1. LeetCode 895. Maximum Frequency Stack

    题目链接:https://leetcode.com/problems/maximum-frequency-stack/ 题意:实现一种数据结构FreqStack,FreqStack需要实现两个功能: ...

  2. 【LeetCode】895. Maximum Frequency Stack 解题报告(Python)

    [LeetCode]895. Maximum Frequency Stack 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxueming ...

  3. [Swift]LeetCode895. 最大频率栈 | Maximum Frequency Stack

    Implement FreqStack, a class which simulates the operation of a stack-like data structure. FreqStack ...

  4. 最大频率栈 Maximum Frequency Stack

    2018-10-06 22:01:11 问题描述: 问题求解: 为每个频率创建一个栈即可. class FreqStack { Map<Integer, Integer> map; Lis ...

  5. LeetCode - Maximum Frequency Stack

    Implement FreqStack, a class which simulates the operation of a stack-like data structure. FreqStack ...

  6. LeetCode OJ:Min Stack(最小栈问题)

    Design a stack that supports push, pop, top, and retrieving the minimum element in constant time. pu ...

  7. Maximum Frequency Stack

    Implement FreqStack, a class which simulates the operation of a stack-like data structure. FreqStack ...

  8. LeetCode Monotone Stack Summary 单调栈小结

    话说博主在写Max Chunks To Make Sorted II这篇帖子的解法四时,写到使用单调栈Monotone Stack的解法时,突然脑中触电一般,想起了之前曾经在此贴LeetCode Al ...

  9. Leetcode 946. Validate Stack Sequences 验证栈序列

    946. Validate Stack Sequences 题目描述 Given two sequences pushed and popped with distinct values, retur ...

随机推荐

  1. 八、Spring之深入理解声明式事务

    Spring之深入理解声明式事务 何为事务? 事务就是把一系列的动作当成一个独立的工作单元,这些动作要么全部完成,要么全部不起作用. 事务的四个属性: 1.原子性(atomicity) 事务是原子性操 ...

  2. COMP 2406 – F19

    COMP 2406 – F19 – A4 Due Friday, November 22nd at 11:59 PMAssignment 4 Trivia Quiz BuilderSubmit a s ...

  3. Django学习笔记(15)——中间件

    当Django处理一个Request的过程是首先通过中间件,然后再通过默认的URL方式进行的.我们可以在Middleware这个地方把所有Request拦截住,用我们自己的方式完成处理以后直接返回Re ...

  4. 【JS】---4用JS获取地址栏参数方法

    用JS获取地址栏参数方法 // 方法一:采用正则表达式获取地址栏参数:( 强烈推荐,既实用又方便!) function GetQueryString(name) { var reg = new Reg ...

  5. .net core 发布到iis问题 HTTP Error 500.30 - ANCM In-Process Start Failure

    1. 没有在Program里配置IIS webBuilder.UseIIS(); 2. StartupProduction 里AutoFac容器注入错误和新版的CORS中间件已经阻止使用允许任意Ori ...

  6. 前端移动框架Framework7入门

    正版官网:https://framework7.io/  (英文) 对应国内:http://www.framework7.cn/ (中文) 本地构建步骤(Demo级别) 1.HTML结构 2.引入Fr ...

  7. JavaScript 设计模式分类

    设计模式的目的是为了提高代码的整洁性.降低代码的资源占用量. JS中的设计模式可分为以下三种: 1. 创建型设计模式 说明:专注于处理对象创建的机制,以合适的方式创建对象,以此来降低创建对象过程的复杂 ...

  8. JavaScript prototype原型用法

    JavaScript对象原型 所有JavaScript对象都从原型继承属性和方法. <!DOCTYPE html> <html> <meta charset=" ...

  9. php取整的几种方式,四舍五入,舍去法取整,进一法取整

    php取整的几种方式,四舍五入,舍去法取整,进一法取整方式一:round 对浮点数进行四舍五入语法:float round ( float val [, int precision] ) echo r ...

  10. dtd语法

    dtd语法 <!ELEMENT 元素名 约束> //简单元素三种:没有子元素的元素 eg: <!ELEMENT name (#PCDATA)> (#PCDATA):约束name ...