php实现最大频率栈 数据结构

7 篇文章 0 订阅
1 篇文章 0 订阅

力扣第895题

实现 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。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-frequency-stack
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

简而言之, 一直往该数据结构里面push整数, 和往外pop. pop的时候要把push次数最多,同样多就是最后push那个数字弹出.
那么用一个键值对数组来存储数据是不错的选择.出现次数为键, 出现相同次数的数字组成一个数组作为值
譬如按顺序push 1 2 3 3 2 3 3 1 1
初始数组values = [];

push(1);
$values = [
	1=>[1]
];

push(2);
$values = [
	1=>[1,2]
];

push(3);
$values = [
	1=>[1,2,3]
];

push(3);
$values = [
	1=>[1,2,3],
	2=>[3]
];

push(2);
$values = [
	1=>[1,2,3],
	2=>[3,2]
];

push(3);
$values = [
	1=>[1,2,3],
	2=>[3,2],
	3=>[3]
];

push(3);
$values = [
	1=>[1,2,3],
	2=>[3,2],
	3=>[3],
	4=>[3]
];
push(1);
$values = [
	1=>[1,2,3],
	2=>[3,2,1],
	3=>[3],
	4=>[3]
];

push(1);
$values = [
	1=>[1,2,3],
	2=>[3,2,1],
	3=>[3,1],
	4=>[3]
];

像这样的就很容易知道弹出顺序应该是 3 1 3 1 2 3 3 2 1

但是再一次push(1)的时候, 怎么知道应当把它存入到键为3的数组下面呢?

方案一:

从第一个开始遍历, 如果当前出现次数下的数组没有1则在当前出现次数下加入该数字并返回,否则去判断下一个.不占用额外空间,但时间复杂度较高
定义私有变量$values

    private $values = [];

那么push方法如下

    function push($x) {
        $time = 1;
        foreach ($this->values as $time=>$value) {
            if (!isset($value[$x])){
                $time--;
                break;
            }
        }
        $this->values[++$time] [$x]= $x;
        return null;
    }

pop方法如下

    function pop() {
        end($this->values);
        $time = key($this->values);
        $int = array_pop($this->values[$time]);
        if (!$this->values[$time]){
            array_pop($this->values);
        }
        return $int;
    }

运行结果如下: 用时1912ms, 内存30.6MB
在这里插入图片描述

方案二:

为了更容易找到当前数字N出现到第几次了,再加一个数组来存储每个数字的出现次数

$times = [
	1=>3,
	2=>2,
	3=>4
]

这样子在再次推入1的时候就很容易知道应该把它加入到下标为4的数组下面了. 在push和pop操作的时候要维护$values和$times两个数组. 占用额外空间但时间复杂度较低
定义私有变量

    private $values = [];
   private $times = [];

push方法如下:

    function push($x) {
       if (isset($this->times[$x])){
           $this->times[$x]++;
       }else{
           $this->times[$x] = 1;
       }
       $this->values[$this->times[$x]] [$x] = $x;
       return null;
   }

pop方法如下:

   function pop() {
       end($this->values);
       $time = key($this->values);
       $int = array_pop($this->values[$time]);
       if (!$this->values[$time]){
           array_pop($this->values);
       }
       $this->times[$int]--;
       return $int;
   }

运行结果如下: 用时228ms, 内存31.3MB
在这里插入图片描述
显然方案二多消耗一点点内存, 大大缩减了执行用时

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值