LeetCode895.最大频率栈
原题链接:最大频率栈
alt RNUOOB 图标

1. 需要了解的知识点

数据结构

栈结构:后进先出(LIFO) 例:12345进入54321出
unordered_map: 哈希函数组成的 无序 map。(此题unordered_map无序比有序map效率更高)

vector的API

empty()      判断Vector是否为空
back()         返回最末一个元素
push_back()    在Vector最后添加一个元素
pop_back()      移除最后一个元素

2. 思路

确定需要定义的变量类型:

  • unordered_map<int,int> maps: 键值key里储存元素(int),值value对应元素频率(int)
  • unordered_map<int,vector<int>> res_maps: 键值key里储存元素频率(vector<int>),值value对应该频率下的元素(int)
  • int max: 此时栈类最大的频率

3. 难点:

个人观点难点在于:(如果最频繁的元素不只一个,则移除并返回最接近栈顶的元素)。

也就是说:当出现多个为最频繁的数,元素频率都相等,这种情况就要考虑哪个元素是最后入栈,该元素就是我们需要移除并返回的数;

4. 代码注释

class FreqStack {
public:
    FreqStack() {
        max = 0;             /*初始化max*/
    }
    void push(int x) {      /*压栈*/
        maps[x]++;           /*将各个元素的频率放入map中*/

      res_maps[maps[x]].push_back(x);     /*vector增加一个元素*/  
/*
**** 如果理解不了上面一行替换成下面三行代码也是一样的,就是会增加内存
      vector<int> vec= res_maps[maps[x]]; 
            vec.push_back(x); 
            res_maps[maps[x]] = vec;
*/
        if (maps[x] > max)      /*在压栈过程中找频率最大的数*/
            max = maps[x];
    }
    int pop() {                /*弹出栈顶*/
        int res = res_maps[max].back(); /*取出最大频率数(pop的结果)*/
        res_maps[max].pop_back();       /*删除最大频率的键值对*/
        maps[res]--;                    /*maps下的频率减一*/

        if (res_maps[max].empty())  /*这操作比较难理解*/
            max--;                  /*说明该频率下已经没有元素了,频率减一*/
        return res;
    }
private:
    unordered_map<int,int> maps;
    unordered_map<int,vector<int>> res_maps;
    int max;
    
};
/**
 * Your FreqStack object will be instantiated and called as such:
 * FreqStack* obj = new FreqStack();
 * obj->push(x);
 * int param_2 = obj->pop();
 */

4. 总结反思

假如原本x的频率为1,增加之后变成2,这里只是在频率为2的vector里新增了一个x,但是并没有删除频率为1的vector中的x。
这样可以保证,当x被弹出(pop)之后,在频率为1的vector里元素的顺序不会被修改。

5. 我写过的智障思路代码

   private: 
    multimap<int,std::pair<int, stack<int>>> maps;
    multimap<std::pair<int, int>,std::pair<int,stack<int>>> maps_pop;
    int count;
   /*看我定义的这类型就知道这写过的代码写的有多智障,频率增加后删除原先的频率就定义成这副鬼样子*/