leetcode 895. Maximum Frequency Stack(python)

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

描述

Design a stack-like data structure to push elements to the stack and pop the most frequent element from the stack.

Implement the FreqStack class:

  • FreqStack() constructs an empty frequency stack.
  • void push(int val) pushes an integer val onto the top of the stack.
  • int pop() removes and returns the most frequent element in the stack.
  • If there is a tie for the most frequent element, the element closest to the stack's top is removed and returned.

Example 1:

Input
["FreqStack", "push", "push", "push", "push", "push", "push", "pop", "pop", "pop", "pop"]
[[], [5], [7], [5], [7], [4], [5], [], [], [], []]
Output
[null, null, null, null, null, null, null, 5, 7, 5, 4]

Explanation
FreqStack freqStack = new FreqStack();
freqStack.push(5); // The stack is [5]
freqStack.push(7); // The stack is [5,7]
freqStack.push(5); // The stack is [5,7,5]
freqStack.push(7); // The stack is [5,7,5,7]
freqStack.push(4); // The stack is [5,7,5,7,4]
freqStack.push(5); // The stack is [5,7,5,7,4,5]
freqStack.pop();   // return 5, as 5 is the most frequent. The stack becomes [5,7,5,7,4].
freqStack.pop();   // return 7, as 5 and 7 is the most frequent, but 7 is closest to the top. The stack becomes [5,7,5,4].
freqStack.pop();   // return 5, as 5 is the most frequent. The stack becomes [5,7,4].
freqStack.pop();   // return 4, as 4, 5 and 7 is the most frequent, but 4 is closest to the top. The stack becomes [5,7].
复制代码

Note:

0 <= val <= 10^9
At most 2 * 10^4 calls will be made to push and pop.
It is guaranteed that there will be at least one element in the stack before calling pop.
复制代码

解析

这周出的题真的是和 stack 卯上了,天天都是 stack ,今天也不例外,而且这道题难度是 HARD 。

根据题意,设计一个类似栈的数据结构,将元素压入栈中,并从栈中弹出出现 频率的元素。

实现 FreqStack 类:

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

题目已经在明显不过了, 肯定要用 stack 做,这道题中将元素压入 stack 中不难,难的是怎么能把出现频率最高的元素返回,或者是有多个出现频率最高的元素,我们删除并返回距离栈顶最近的那个元素。其实这道题我一开始的方向错了,我要用字典去记录每个元素出现的个数和位置,并对他们进行排序来实现题目中返回元素的逻辑,这种很明显是超时的,而且实现起来比较复杂。

之后我看了论坛大佬的解法才惊呼巧妙,因为一方面我们关心每个元素的出现频率,另一方面我们又要关心如何最大频率元素,所以这里定义了一个 group 字典成为从频率到具有该频率的元素栈的映射,我们定义了一个全局变量 maxFreq 来最大的频率,使用计数器 c 对所有元素的出现个数进行计数。

当执行 push 元素 x 的时候,我们对 c[x] 加一表示为 f ,表示出现频率增一,然后判断其与 maxFreq 的关系,如果 f 较大说明到目前为止栈中出现的最大频率 maxFreq 应该更新为 f ,否则就直接将 x 加入到 group[f] 中。

当执行 pop 的时候,我们已经知道了目前栈中的最大出现频率 maxFreq ,所以我们直接弹出 group[maxFreq].pop() 为 v 即可,然后我们将 c[v] 减一,表示 v 的出现频率减一,如果此时 group[maxFreq] 为空,则将 maxFreq 减一,我们可以去找频率降低之后的相关元素,最后返回 v 即可。

因为整个过程都是字典操作,所以时间复杂度为 O(1) ,空间复杂度为 O(N) 。

解答

class FreqStack(object):
    def __init__(self):
        self.group = defaultdict(list)
        self.c = collections.Counter()
        self.maxFreq = 0
    def push(self, x):
        self.c[x] += 1
        f = self.c[x]
        if f > self.maxFreq:
            self.maxFreq = f
        self.group[f].append(x)
    def pop(self):
        v = self.group[self.maxFreq].pop()
        self.c[v] -= 1
        if not self.group[self.maxFreq]:
            self.maxFreq -= 1
        return v            	      
		
复制代码

运行结果

37 / 37 test cases passed.
Status: Accepted
Runtime: 328 ms
Memory Usage: 22.7 MB
复制代码

原题链接:leetcode.com/problems/ma…

您的支持是我最大的动力

Supongo que te gusta

Origin juejin.im/post/7077036396296273933
Recomendado
Clasificación