0895-最大频率栈

Raphael Liu Lv10

设计一个类似堆栈的数据结构,将元素推入堆栈,并从堆栈中弹出 出现频率 最高的元素。

实现 FreqStack 类:

  • FreqStack() 构造一个空的堆栈。
  • void push(int val) 将一个整数 val 压入栈顶。
  • int pop() 删除并返回堆栈中出现频率最高的元素。
    • 如果出现频率最高的元素不只一个,则移除并返回最接近栈顶的元素。

示例 1:

**输入:**
["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 <= 109
  • pushpop 的操作数不大于 2 * 104
  • 输入保证在调用 pop 之前堆栈中至少有一个元素。

方法一:哈希表和栈

思路与算法

在本题中,每次需要优先弹出频率最大的元素,如果频率最大元素有多个,则优先弹出靠近栈顶的元素。因此,我们可以考虑将栈序列分解为多个频率不同的栈序列,每个栈维护同一频率的元素。当元素入栈时频率增加,将元素加入到更高频率的栈中,低频率栈中的元素不需要出栈。当元素出栈时,将频率最高的栈的栈顶元素出栈即可。

更详细的,我们用一个哈希表 freq 来记录每个元素出现的次数。设当前最大频率为 maxFreq,为 1 \sim \textit{maxFreq 中的每种频率单独设置一个栈。为了方便描述,记 freq}[x] 为 x 的频率,group}[i] 为频率为 i 的栈。

  1. 当元素 x 入栈时,令 freq}[x] + 1,然后将 x 放入 group}[\textit{freq}[x]] 中,更新 maxFreq} = \max(\textit{maxFreq}, \textit{freq}[x])。此时,group}[1] \sim \textit{group}[\textit{freq}[x]] 的每一个栈中都包含 x。
  2. 元素出栈时,获取 x = \textit{group}[\textit{maxFreq}].top() 作为出栈元素,令 freq}[x] - 1,若 x 出栈后 group}[\textit{maxFreq}] 为空,则令 maxFreq} - 1。

代码

[sol1-Python3]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class FreqStack:
def __init__(self):
self.freq = defaultdict(int)
self.group = defaultdict(list)
self.maxFreq = 0

def push(self, val: int) -> None:
self.freq[val] += 1
self.group[self.freq[val]].append(val)
self.maxFreq = max(self.maxFreq, self.freq[val])

def pop(self) -> int:
val = self.group[self.maxFreq].pop()
self.freq[val] -= 1
if len(self.group[self.maxFreq]) == 0:
self.maxFreq -= 1
return val
[sol1-C++]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class FreqStack {
public:
FreqStack() {
maxFreq = 0;
}

void push(int val) {
freq[val]++;
group[freq[val]].push(val);
maxFreq = max(maxFreq, freq[val]);
}

int pop() {
int val = group[maxFreq].top();
freq[val]--;
group[maxFreq].pop();
if (group[maxFreq].empty()) {
maxFreq--;
}
return val;
}

private:
unordered_map<int, int> freq;
unordered_map<int, stack<int>> group;
int maxFreq;
};
[sol1-Java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class FreqStack {
private Map<Integer, Integer> freq;
private Map<Integer, Deque<Integer>> group;
private int maxFreq;

public FreqStack() {
freq = new HashMap<Integer, Integer>();
group = new HashMap<Integer, Deque<Integer>>();
maxFreq = 0;
}

public void push(int val) {
freq.put(val, freq.getOrDefault(val, 0) + 1);
group.putIfAbsent(freq.get(val), new ArrayDeque<Integer>());
group.get(freq.get(val)).push(val);
maxFreq = Math.max(maxFreq, freq.get(val));
}

public int pop() {
int val = group.get(maxFreq).peek();
freq.put(val, freq.get(val) - 1);
group.get(maxFreq).pop();
if (group.get(maxFreq).isEmpty()) {
maxFreq--;
}
return val;
}
}
[sol1-C#]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class FreqStack {
private IDictionary<int, int> freq;
private IDictionary<int, Stack<int>> group;
private int maxFreq;

public FreqStack() {
freq = new Dictionary<int, int>();
group = new Dictionary<int, Stack<int>>();
maxFreq = 0;
}

public void Push(int val) {
if (!freq.ContainsKey(val)) {
freq.Add(val, 0);
}
freq[val]++;
if (!group.ContainsKey(freq[val])) {
group.Add(freq[val], new Stack<int>());
}
group[freq[val]].Push(val);
maxFreq = Math.Max(maxFreq, freq[val]);
}

public int Pop() {
int val = group[maxFreq].Peek();
freq[val]--;
group[maxFreq].Pop();
if (group[maxFreq].Count == 0) {
maxFreq--;
}
return val;
}
}
[sol1-Golang]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
type FreqStack struct {
freq map[int]int
group map[int][]int
maxFreq int
}

func Constructor() FreqStack {
return FreqStack{map[int]int{}, map[int][]int{}, 0}
}

func (f *FreqStack) Push(val int) {
f.freq[val]++
f.group[f.freq[val]] = append(f.group[f.freq[val]], val)
f.maxFreq = max(f.maxFreq, f.freq[val])
}

func (f *FreqStack) Pop() int {
val := f.group[f.maxFreq][len(f.group[f.maxFreq])-1]
f.group[f.maxFreq] = f.group[f.maxFreq][:len(f.group[f.maxFreq])-1]
f.freq[val]--
if len(f.group[f.maxFreq]) == 0 {
f.maxFreq--
}
return val
}

func max(a, b int) int {
if b > a {
return b
}
return a
}
[sol1-JavaScript]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var FreqStack = function() {
this.freq = new Map();
this.group = new Map();
this.maxFreq = 0;
};

FreqStack.prototype.push = function(val) {
this.freq.set(val, (this.freq.get(val) || 0) + 1);
if (!this.group.has(this.freq.get(val))) {
this.group.set(this.freq.get(val), []);
}
this.group.get(this.freq.get(val)).push(val);
this.maxFreq = Math.max(this.maxFreq, this.freq.get(val));
};

FreqStack.prototype.pop = function() {
const val = this.group.get(this.maxFreq)[this.group.get(this.maxFreq).length - 1];
this.freq.set(val, this.freq.get(val) - 1);
this.group.get(this.maxFreq).pop();

if (this.group.get(this.maxFreq).length === 0) {
this.maxFreq--;
}
return val;
};
[sol1-C]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#define MAX(a, b) ((a) > (b) ? (a) : (b))

typedef struct {
struct ListNode *head;
int stackSize;
} Stack;

typedef struct {
int key;
int val;
UT_hash_handle hh;
} HashFreqItem;

typedef struct {
int key;
Stack *val;
UT_hash_handle hh;
} HashGroupItem;

typedef struct {
HashFreqItem *freq;
HashGroupItem *group;
int maxFreq;
} FreqStack;

Stack* stackCreate() {
Stack *obj = (Stack *)malloc(sizeof(Stack));
obj->head= NULL;
obj->stackSize = 0;
return obj;
}

bool stackEmpty(Stack *obj) {
return obj->stackSize == 0;
}

bool stackPush(Stack *obj, int val) {
struct ListNode *p = (struct ListNode *)malloc(sizeof(struct ListNode));
p->val = val;
p->next = obj->head;
obj->head = p;
obj->stackSize++;
return true;
}

int stackPop(Stack *obj) {
if (stackEmpty(obj)) {
return -1;
}
int ret = obj->head->val;
obj->head = obj->head->next;
obj->stackSize--;
return ret;
}

void stackFree(Stack *obj) {
for (struct ListNode * cur = obj->head; cur;) {
struct ListNode *p = cur;
cur = cur->next;
free(p);
}
free(obj);
}

FreqStack* freqStackCreate() {
FreqStack *obj = (FreqStack *)malloc(sizeof(FreqStack));
obj->maxFreq = 0;
obj->freq = NULL;
obj->group = NULL;
return obj;
}

void freqStackPush(FreqStack* obj, int val) {
HashFreqItem *pFreqEntry = NULL;
HASH_FIND_INT(obj->freq, &val, pFreqEntry);
if (pFreqEntry == NULL) {
pFreqEntry = (HashFreqItem *)malloc(sizeof(HashFreqItem));
pFreqEntry->key = val;
pFreqEntry->val = 1;
HASH_ADD_INT(obj->freq, key, pFreqEntry);
} else {
pFreqEntry->val++;
}
int freq = pFreqEntry->val;
HashGroupItem *pGroupEntry = NULL;
HASH_FIND_INT(obj->group, &freq, pGroupEntry);
if (pGroupEntry == NULL) {
pGroupEntry = (HashGroupItem *)malloc(sizeof(HashGroupItem));
pGroupEntry->key = freq;
pGroupEntry->val = stackCreate();
HASH_ADD_INT(obj->group, key, pGroupEntry);
}
stackPush(pGroupEntry->val, val);
obj->maxFreq = MAX(obj->maxFreq, freq);
}

int freqStackPop(FreqStack* obj) {
int freq = obj->maxFreq;
HashGroupItem *pGroupEntry = NULL;
HASH_FIND_INT(obj->group, &freq, pGroupEntry);
int val = stackPop(pGroupEntry->val);
if (stackEmpty(pGroupEntry->val)) {
obj->maxFreq--;
}
HashFreqItem *pFreqEntry = NULL;
HASH_FIND_INT(obj->freq, &val, pFreqEntry);
pFreqEntry->val--;
return val;
}

void freqStackFree(FreqStack* obj) {
HashFreqItem *pCurr = NULL, *pNext = NULL;
HASH_ITER(hh, obj->freq, pCurr, pNext) {
HASH_DEL(obj->freq, pCurr);
free(pCurr);
}
HashGroupItem *pGroupCurr = NULL, *pGroupNext = NULL;
HASH_ITER(hh, obj->group, pGroupCurr, pGroupNext) {
HASH_DEL(obj->group, pGroupCurr);
stackFree(pGroupCurr->val);
free(pGroupCurr);
}
free(obj);
}

复杂度分析

  • 时间复杂度:对于 push 和 pop 操作,时间复杂度为 O(1)。

  • 空间复杂度:O(n),其中 n 是 FreqStack 中元素的个数。

 Comments
On this page
0895-最大频率栈