「雜湊表」最大頻率棧(力扣第895題)
阿新 • • 發佈:2022-11-30
本題為11月30日力扣每日一題
題目來源:力扣第895題
題目tag:雜湊表
題面
題目描述
設計一個類似堆疊的資料結構,將元素推入堆疊,並從堆疊中彈出出現頻率最高的元素。
實現 FreqStack 類:
- FreqStack() 構造一個空的堆疊。
- void push(int val) 將一個整數 val 壓入棧頂。
- int pop() 刪除並返回堆疊中出現頻率最高的元素。如果出現頻率最高的元素不只一個,則移除並返回最接近棧頂的元素。
示例
輸入:
["FreqStack","push","push","push","push","push","push","pop","pop","pop","pop"], [[],[5],[7],[5],[7],[4],[5],[],[],[],[]]
輸出:
[null,null,null,null,null,null,null,5,7,5,4]
解釋:
FreqStack = new FreqStack(); 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 出現頻率最高。堆疊變成 [5,7,5,7,4]。 freqStack.pop(); //返回 7 ,因為 5 和 7 出現頻率最高,但7最接近頂部。堆疊變成 [5,7,5,4]。 freqStack.pop(); //返回 5 ,因為 5 出現頻率最高。堆疊變成 [5,7,4]。 freqStack.pop(); //返回 4 ,因為 4, 5 和 7 出現頻率最高,但 4 是最接近頂部的。堆疊變成 [5,7]。
提示
0 <= val <= $ 10^9 $
push 和 pop 的運算元不大於 $ 2 * 10^4 $。
輸入保證在呼叫 pop 之前堆疊中至少有一個元素。
思路分析
就我個人而言,當我看到題目要實現一個最大頻率棧的時候,我的第一反應是使用單調棧
來解決(只是第一反應).而要維護這樣一個單調棧,就需要能在常數時間中取得當前元素的頻率
而每次在常數時間中取得當前元素的頻率這件事,顯然只需要將元素作為鍵,將出現頻率作為值,利用雜湊表
就可以完成了.想到這裡我突然發現彈出最大頻率元素也可以用雜湊表
就可以直接解決了.
我們只需要維護一個雜湊表
,它以出現頻率為鍵,以這個頻率所有元素組成的棧
或許這題的難點也在這裡,資料的物理結構
和邏輯結構
並不需要完全對應,甚至可以完全不一樣.因為對外來說,內部的結構都是不可見的,所以只需要能完成指定的行為即可,無需拘泥於特定的形式.
參考程式碼
class FreqStack
{
private:
// 最大頻率
int maxFreq;
// 記錄各個數頻率用的桶
unordered_map<int, int> book;
// 每個頻率對應的元素組成的各個棧的集合
unordered_map<int, stack<int>> bucket;
public:
/*
初始化物件
在C++中此處只需要初始化最大頻率屬性即可
*/
FreqStack()
{
maxFreq = 0;
}
/*
元素入棧
*/
void push(int val)
{
book[val]++; // 更新當前元素出現頻率
bucket[book[val]].push(val); // 將元素推入對應頻率的棧中
maxFreq = max(maxFreq, book[val]); // 更新最大頻率
}
int pop()
{
// 取出最大頻率對應的棧頂元素
int res = bucket[maxFreq].top();
bucket[maxFreq].pop();
// 料理後事
book[res]--;
if (bucket[maxFreq].empty()) // 如果空了,手動減小最大頻率
{
maxFreq--;
}
return res;
}
};
/**
* Your FreqStack object will be instantiated and called as such:
* FreqStack* obj = new FreqStack();
* obj->push(val);
* int param_2 = obj->pop();
*/
"正是我們每天反覆做的事情,最終造就了我們,優秀不是一種行為,而是一種習慣" ---亞里士多德