【设计】A012_LC_最大频率栈(pq + map / map + stack)

一、Problem

实现 FreqStack,模拟类似栈的数据结构的操作的一个类。FreqStack 有两个函数:

  • push(int x),将整数 x 推入栈中。
  • 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]
解释:
执行六次 .push 操作后,栈自底向上为 [5,7,5,7,4,5]。然后:

pop() -> 返回 5,因为 5 是出现频率最高的。
栈变成 [5,7,5,7,4]。

pop() -> 返回 7,因为 5 和 7 都是频率最高的,但 7 最接近栈顶。
栈变成 [5,7,5,4]。

pop() -> 返回 5 。
栈变成 [5,7,4]。

pop() -> 返回 4 。
栈变成 [5,7]。

提示:

对 FreqStack.push(int x) 的调用中 0 <= x <= 10^9。
如果栈的元素数目为零,则保证不会调用 FreqStack.pop()。
单个测试样例中,对 FreqStack.push 的总调用次数不会超过 10000。
单个测试样例中,对 FreqStack.pop 的总调用次数不会超过 10000。
所有测试样例中,对 FreqStack.push 和 FreqStack.pop 的总调用次数不会超过 150000。

二、Solution

方法一:pq + map

我们需要关心两个因素:元素距离栈顶的位置、元素频次

比较直观的做法是用排序做,pq 按照上述两个字段进行排序,

class FreqStack {
    Queue<int[]> q; // a[0]值;a[1]频率;a[2]离栈顶位置
    Map<Integer, Integer> m;
    int top;
    
    public FreqStack() {
        q = new PriorityQueue<>((e1, e2) -> {
            if (e1[1] == e2[1]) 
            	return e2[2]-e1[2];
            return e2[1]-e1[1];
        });
        m = new HashMap<>();
        top = 0;
    }
    
    public void push(int x) {
        int c = m.getOrDefault(x, 0)+1;
        q.add(new int[]{x, c, top++});
        m.put(x, c);
    }
    
    public int pop() {
        int[] a = q.poll();
        m.put(a[0], m.get(a[0])-1);
        return a[0];
    }
}

复杂度分析

  • 时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)
  • 空间复杂度: O ( n ) O(n) O(n)

更优的 O ( n ) O(n) O(n) 的做法是利用一个 map,:

  • key 为各个频次 c
  • value 为存储该频次的所有元素的栈 st,栈顶就是最新的元素
class FreqStack {
public:
	unordered_map<int, int> cnt;
	unordered_map<int, stack<int>> m;
	int maxc;
    FreqStack() {
    }
    
    void push(int x) {
    	int c = ++cnt[x];
    	if (c > maxc) maxc = c;
    	m[c].push(x);
    }
    
    int pop() {
        int v = m[maxc].top(); m[maxc].pop(); cnt[v]--;
        if (m[maxc].size() == 0) maxc--;
    	return v;
    }
};

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n)

你可能感兴趣的:(#,【设计】,map,堆,栈)