跳到主要内容

895. Max Frequency Stack

Maximum Frequency Stack

这种题的关键 通常都看pop()方法想干嘛

要我们移除且返回栈中频率最高的元素

如果频率最高的元素有多个并列 选最接近栈顶的

最接近栈顶的翻译:最晚被纳入的

因此需要对每个频率维持栈的结构

才好在Tiebreaker下 拿到最晚被纳入的元素

栈中栈

架构描绘

(1). 频率栈:这是 外层 结构 每当本来最高的频率

其所含元素被清光 这个频率就不再是最高

需要挪出栈 让栈顶留给下一个频率体现变化

(2). 元素栈:这是 内层 结构 每个频率有专属元素栈

同样频率下 越晚升上来这频率的元素 越靠近栈顶

正是题目强调的Tiebreaker的体现

因此我们先开个frequencyStack的外栈

栈上每个索引ii 代表频率ii

每个频率ii上又内栈 储存频率为ii的元素

方法实现

一、push(int value):一旦被呼叫

先在哈希表给value的出场频率+1

假设更新后的频率来到了xx

就在外栈上寻找索引为xx的内栈

value放到这个内栈最顶端

因此如果发现xx等于外栈长度时

说明目前外栈只反映到频率x1x - 1

需要在外栈顶开个新内栈储存频率xx

二、pop():每次运作时 首先将外栈上

最顶部的内栈 弹出其栈顶元素

在哈希表把被弹元素的频率-1

这便是频率最高的元素中最接近栈顶的

接著检查外栈顶的内栈是否被清空

空掉的话 自然也请这个内栈弹离开外栈

精确反映目前最大频率的变化


class MaxFrequencyStack: # LeetCode Q.895.
def __init__(self):
self.vals_freqs: dict[int, int] = dict()

# Each idx contains stack of values w/ frequency = idx.
# Pad empty stack to adjust for 0-based indexing.
self.freqs_stacks: list[list[int]] = [[]]

def push(self, value: int) -> None:
if value not in self.vals_freqs.keys():
self.vals_freqs.update({value: 0})
self.vals_freqs[value] += 1

# Need to add another stack for current frequency.
if self.vals_freqs[value] == len(self.freqs_stacks):
self.freqs_stacks.append([])

frequency = self.vals_freqs[value]
self.freqs_stacks[frequency].append(value)

def pop(self) -> int:
most_freq_val = self.freqs_stacks[-1].pop(-1)

if not self.freqs_stacks[-1]: self.freqs_stacks.pop(-1)

self.vals_freqs[most_freq_val] -= 1
return most_freq_val

Stack of Stacks_Efficiency 时间复杂度在push(int value)pop()都是O(1)O(1) 空间则是有O(n)O(n)

可别像Algo Monster搞heaps弄成O(logn)O(logn)时间复杂度欸