题解 | #用两个栈实现队列#我用均摊复杂度 已经击败100%的对手啦!

思路如下

无论是「用栈实现队列」还是说「用队列实现栈」,其实思路都是类似的。

都可以通过用两个 栈或者队列 来解决。

现在我们创建两个栈,分别是 outin,用作处理「输出」和「输入」两个操作。

其实就是两个栈来回的「倒腾」

而对于「何时倒腾」决定了是 O(n) 解法 还是 均摊 O(1) 解法

1 先来说 O(n) 解法

我们创建两个栈,分别是 out 和 in:

  • in 用作处理输入操作 push(),使用 in 时需确保 out 为空
  • out 用作处理输出操作 pop() 和 peek(),使用 out 时需确保 in 为空
class MyQueue {
    Deque<Integer> out, in;
    public MyQueue() {
        in = new ArrayDeque<>();
        out = new ArrayDeque<>();
    }
    
    public void push(int x) {
        while (!out.isEmpty()) in.addLast(out.pollLast());
        in.addLast(x);
    }
    
    public int pop() {
        while (!in.isEmpty()) out.addLast(in.pollLast());
        return out.pollLast();
    }
    
    public int peek() {
        while (!in.isEmpty()) out.addLast(in.pollLast());
        return out.peekLast();
    }
    
    public boolean empty() {
        return out.isEmpty() && in.isEmpty();
    }
}
  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

2 再来说均摊 O(1) 解法

事实上,我们不需要在每次的「入栈」和「出栈」操作中都进行「倒腾」。

我们只需要保证,输入的元素总是跟在前面的输入元素的后面就行啦,而输出元素总是最早输入的那个元素即可

我们可以通过调整「倒腾」的时机来确保满足上述要求,但又不需要发生在每一次操作中:

  • 即只有在「输出栈」为空的时候,才发生一次性的「倒腾」
//java的版本
class MyQueue {
    Deque<Integer> out, in;
    public MyQueue() {
        in = new ArrayDeque<>();
        out = new ArrayDeque<>();
    }
    
    public void push(int x) {
        in.addLast(x);
    }
    
    public int pop() {
        if (out.isEmpty()) {
            while (!in.isEmpty()) out.addLast(in.pollLast());
        }
        return out.pollLast();
    }
    
    public int peek() {
        if (out.isEmpty()) {
            while (!in.isEmpty()) out.addLast(in.pollLast());
        }
        return out.peekLast();
    }
    
    public boolean empty() {
        return out.isEmpty() && in.isEmpty();
    }
}
  • 时间复杂度:pop() 和 peek()两个操作都是均摊,所以是O(1)
  • 空间复杂度:O(n)

你可能没听过均摊复杂度

3 我说明下

我们可以用另外一个例子来理解「均摊复杂度」,你就明白了,大家都知道「哈希表」的底层是通过数组来实现的。

正常情况下,我们要算元素在哈希桶的位置,然后放入哈希桶里面,复杂度为 O(1),我们可以通过简单的“拉链法”搭配「头插法」方式来解决哈希冲突的问题。

但是当某次元素插入后,「哈希表」能达到扩容的阈值,那么需要对底层所使用的数组进行扩容,这个复杂度是 O(n)

很显然「扩容」操作不会发生在每一次的元素插入中,扩容的 O(n) 都会伴随着 n 次的 O(1),换句话说 O(n) 的复杂度会被均摊到每一次插入当中去,所以哈希表插入仍然还是 O(1) 的。

同样的道理,我们的「倒腾」也不是发生在每一次的「输出操作」中,而是集中发生在一次「输出栈为空」的这个时候,所以 poppeek 都是均摊复杂度为 O(1) 的操作。

由于本题的调用次数它只有 100 次,所以铁定是一个人均 100% 的算法(也就是花费 0 ms)🐶 🐶

但是我们需要对操作进行复杂度分析进行判断,而不是看时间来判断自己是不是均摊 O(1) 哈 ~

全部评论

相关推荐

喜欢吃蛋糕仰泳鲈鱼是我的神:字节可以找个hr 给你挂了,再放池子捞
点赞 评论 收藏
分享
评论
1
收藏
分享
正在热议
# 25届秋招总结 #
440279次浏览 4490人参与
# 春招别灰心,我们一人来一句鼓励 #
41427次浏览 524人参与
# 阿里云管培生offer #
119755次浏览 2219人参与
# 地方国企笔面经互助 #
7922次浏览 18人参与
# 虾皮求职进展汇总 #
113889次浏览 883人参与
# 实习,投递多份简历没人回复怎么办 #
2453837次浏览 34847人参与
# 北方华创开奖 #
107282次浏览 599人参与
# 实习必须要去大厂吗? #
55644次浏览 960人参与
# 同bg的你秋招战况如何? #
75364次浏览 551人参与
# 提前批简历挂麻了怎么办 #
149798次浏览 1977人参与
# 投递实习岗位前的准备 #
1195641次浏览 18546人参与
# 你投递的公司有几家约面了? #
33170次浏览 188人参与
# 双非本科求职如何逆袭 #
661833次浏览 7394人参与
# 机械人春招想让哪家公司来捞你? #
157595次浏览 2267人参与
# 如果公司给你放一天假,你会怎么度过? #
4719次浏览 54人参与
# 如果你有一天可以担任公司的CEO,你会做哪三件事? #
11300次浏览 267人参与
# 发工资后,你做的第一件事是什么 #
12384次浏览 61人参与
# 工作中,努力重要还是选择重要? #
35576次浏览 384人参与
# 参加完秋招的机械人,还参加春招吗? #
20079次浏览 240人参与
# 实习想申请秋招offer,能不能argue薪资 #
39220次浏览 314人参与
# 我的上岸简历长这样 #
451897次浏览 8088人参与
# 非技术岗是怎么找实习的 #
155837次浏览 2120人参与
牛客网
牛客企业服务