[LeetCode] 895. Maximum Frequency Stack 最大頻率棧



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 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: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:數組

  • 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 CacheLFU 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)

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 題目講解彙總(持續更新中...)

相關文章
相關標籤/搜索