Implement FreqStack
, a class which simulates the operation of a stack-like data structure.html
FreqStack
has two functions:git
push(int x)
, which pushes an integer x
onto the stack.pop()
, which removes and returns the most frequent element in the stack.
Example 1:github
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:數組
FreqStack.push(int x)
will be such that 0 <= x <= 10^9
.FreqStack.pop()
won't be called if the stack has zero elements.FreqStack.push
calls will not exceed 10000
in a single test case.FreqStack.pop
calls will not exceed 10000
in a single test case.FreqStack.push
and FreqStack.pop
calls will not exceed 150000
across all test cases.
這道題讓咱們實現一種最大頻率棧,有入棧和出棧功能,須要每次出棧的都是棧中出現頻率最大的數字,如有多個數字的頻率相同,那麼離棧頂最近的元素先出棧。剛開始看到這道題的時候,博主立馬聯想到了 LRU Cache 和 LFU Cache,想着會不會也須要在迭代器上作文章,但實際是我想多了,雖然同爲 Hard 的題目,這道題的解法卻要比以前那兩道要簡單的多。這裏只跟數字出現的頻率有關,只有在頻率相等的狀況下才會考慮棧的後入先出的特性,因此必定是須要統計棧中每一個數字出現的頻率的,咱們使用一個 HashMap 來創建每一個數字跟其出現次數之間的映射。因爲頻率相等的數字可能有多個,因此咱們必須知道某個特性頻率下都有哪些數字,再用一個 HashMap 來創建頻率和該頻率下全部的數字之間的映射,能夠將這些數組放到一個數組或者一個棧中,這裏爲了簡便起見,就使用一個數組了。另外,咱們還須要維護一個當前最大頻率的變量,能夠經過這個值到 HashMap 中快速定位數組的位置。好,一切準備就緒以後就開始解題吧,對於入棧函數 push(),首先須要將x對應的映射值加1,並更新最大頻率 mxFreq,而後就是要把x加入當前頻率對應的數組中,注意若某個數字出現了3次,那麼數字會分別加入頻率爲 1,2,3 的映射數組中。接下來看出棧函數 pop() 如何實現,因爲咱們知道當前最大頻率 mxFreq,就能夠直接去 HashMap 中取出該頻率下的全部數字的數組,題目說了若頻率相等,取離棧頂最近的元素,這裏就是數組末尾的數組,取到以後,要將該數字從數組末尾移除。移除以後,咱們要檢測一下,若數組此時爲空了,說明當前最大頻率下以後一個數字,取出以後,最大頻率就要自減1,還有不要忘記的就是取出數字的自身的頻率值也要自減1,參見代碼以下:函數
解法一:code
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便可,參見代碼以下:htm
解法二:blog
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/895element
參考資料:
https://leetcode.com/problems/maximum-frequency-stack/
https://leetcode.com/problems/maximum-frequency-stack/discuss/163410/C%2B%2BJavaPython-O(1)