跳转至

面试题 03.04. 化栈为队

题目描述

实现一个MyQueue类,该类用两个栈来实现一个队列。


示例:

MyQueue queue = new MyQueue();

queue.push(1);
queue.push(2);
queue.peek(); // 返回 1
queue.pop(); // 返回 1
queue.empty(); // 返回 false


说明:

  • 你只能使用标准的栈操作 -- 也就是只有 push to top, peek/pop from top, sizeis empty 操作是合法的。
  • 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
  • 假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)。

解法

方法一:双栈

思考

栈是后进先出,队列要先进先出。每次入队都把已有元素倒到辅助栈再倒回,正确但使 push 成为线性。

入队与出队的次序相反,只需在出队侧再反转一次。为此用 stk1 只负责入队,stk2 只负责出队;仅当 stk2 为空时才把 stk1 一次性倒入。

move 保证每个元素至多从 stk1 迁到 stk2 一次,出队与取队首均摊 \(O(1)\)。判空则看两栈是否都空。

我们使用两个栈,其中栈 stk1用于入队,另一个栈 stk2 用于出队。

入队时,直接将元素入栈 stk1。时间复杂度 \(O(1)\)

出队时,先判断栈 stk2 是否为空,如果为空,则将栈 stk1 中的元素全部出栈并入栈 stk2,然后再从栈 stk2 中出栈一个元素。如果栈 stk2 不为空,则直接从栈 stk2 中出栈一个元素。均摊时间复杂度 \(O(1)\)

获取队首元素时,先判断栈 stk2 是否为空,如果为空,则将栈 stk1 中的元素全部出栈并入栈 stk2,然后再从栈 stk2 中获取栈顶元素。如果栈 stk2 不为空,则直接从栈 stk2 中获取栈顶元素。均摊时间复杂度 \(O(1)\)

判断队列是否为空时,只要判断两个栈是否都为空即可。时间复杂度 \(O(1)\)

 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
class MyQueue:
    def __init__(self):
        self.stk1 = []
        self.stk2 = []

    def push(self, x: int) -> None:
        self.stk1.append(x)

    def pop(self) -> int:
        self.move()
        return self.stk2.pop()

    def peek(self) -> int:
        self.move()
        return self.stk2[-1]

    def empty(self) -> bool:
        return not self.stk1 and not self.stk2

    def move(self):
        if not self.stk2:
            while self.stk1:
                self.stk2.append(self.stk1.pop())


# Your MyQueue object will be instantiated and called as such:
# obj = MyQueue()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.peek()
# param_4 = obj.empty()
 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
class MyQueue {
    private Deque<Integer> stk1 = new ArrayDeque<>();
    private Deque<Integer> stk2 = new ArrayDeque<>();

    public MyQueue() {
    }

    public void push(int x) {
        stk1.push(x);
    }

    public int pop() {
        move();
        return stk2.pop();
    }

    public int peek() {
        move();
        return stk2.peek();
    }

    public boolean empty() {
        return stk1.isEmpty() && stk2.isEmpty();
    }

    private void move() {
        while (stk2.isEmpty()) {
            while (!stk1.isEmpty()) {
                stk2.push(stk1.pop());
            }
        }
    }
}

/**
 * Your MyQueue object will be instantiated and called as such:
 * MyQueue obj = new MyQueue();
 * obj.push(x);
 * int param_2 = obj.pop();
 * int param_3 = obj.peek();
 * boolean param_4 = obj.empty();
 */
 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
class MyQueue {
public:
    MyQueue() {
    }

    void push(int x) {
        stk1.push(x);
    }

    int pop() {
        move();
        int ans = stk2.top();
        stk2.pop();
        return ans;
    }

    int peek() {
        move();
        return stk2.top();
    }

    bool empty() {
        return stk1.empty() && stk2.empty();
    }

private:
    stack<int> stk1;
    stack<int> stk2;

    void move() {
        if (stk2.empty()) {
            while (!stk1.empty()) {
                stk2.push(stk1.top());
                stk1.pop();
            }
        }
    }
};

/**
 * Your MyQueue object will be instantiated and called as such:
 * MyQueue* obj = new MyQueue();
 * obj->push(x);
 * int param_2 = obj->pop();
 * int param_3 = obj->peek();
 * bool param_4 = obj->empty();
 */
 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
type MyQueue struct {
    stk1 []int
    stk2 []int
}

func Constructor() MyQueue {
    return MyQueue{[]int{}, []int{}}
}

func (this *MyQueue) Push(x int) {
    this.stk1 = append(this.stk1, x)
}

func (this *MyQueue) Pop() int {
    this.move()
    ans := this.stk2[len(this.stk2)-1]
    this.stk2 = this.stk2[:len(this.stk2)-1]
    return ans
}

func (this *MyQueue) Peek() int {
    this.move()
    return this.stk2[len(this.stk2)-1]
}

func (this *MyQueue) Empty() bool {
    return len(this.stk1) == 0 && len(this.stk2) == 0
}

func (this *MyQueue) move() {
    if len(this.stk2) == 0 {
        for len(this.stk1) > 0 {
            this.stk2 = append(this.stk2, this.stk1[len(this.stk1)-1])
            this.stk1 = this.stk1[:len(this.stk1)-1]
        }
    }
}

/**
 * Your MyQueue object will be instantiated and called as such:
 * obj := Constructor();
 * obj.Push(x);
 * param_2 := obj.Pop();
 * param_3 := obj.Peek();
 * param_4 := obj.Empty();
 */
 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
class MyQueue {
    stk1: number[];
    stk2: number[];

    constructor() {
        this.stk1 = [];
        this.stk2 = [];
    }

    push(x: number): void {
        this.stk1.push(x);
    }

    pop(): number {
        this.move();
        return this.stk2.pop();
    }

    peek(): number {
        this.move();
        return this.stk2.at(-1);
    }

    empty(): boolean {
        return !this.stk1.length && !this.stk2.length;
    }

    move(): void {
        if (!this.stk2.length) {
            while (this.stk1.length) {
                this.stk2.push(this.stk1.pop()!);
            }
        }
    }
}

/**
 * Your MyQueue object will be instantiated and called as such:
 * var obj = new MyQueue()
 * obj.push(x)
 * var param_2 = obj.pop()
 * var param_3 = obj.peek()
 * var param_4 = obj.empty()
 */
 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
use std::collections::VecDeque;

struct MyQueue {
    stk1: Vec<i32>,
    stk2: Vec<i32>,
}

impl MyQueue {
    fn new() -> Self {
        MyQueue {
            stk1: Vec::new(),
            stk2: Vec::new(),
        }
    }

    fn push(&mut self, x: i32) {
        self.stk1.push(x);
    }

    fn pop(&mut self) -> i32 {
        self.move_elements();
        self.stk2.pop().unwrap()
    }

    fn peek(&mut self) -> i32 {
        self.move_elements();
        *self.stk2.last().unwrap()
    }

    fn empty(&self) -> bool {
        self.stk1.is_empty() && self.stk2.is_empty()
    }

    fn move_elements(&mut self) {
        if self.stk2.is_empty() {
            while let Some(element) = self.stk1.pop() {
                self.stk2.push(element);
            }
        }
    }
}
 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
class MyQueue {
    private var stk1: [Int] = []
    private var stk2: [Int] = []

    init() {}

    func push(_ x: Int) {
        stk1.append(x)
    }

    @discardableResult
    func pop() -> Int {
        move()
        return stk2.removeLast()
    }

    func peek() -> Int {
        move()
        return stk2.last!
    }

    func empty() -> Bool {
        return stk1.isEmpty && stk2.isEmpty
    }

    private func move() {
        if stk2.isEmpty {
            while !stk1.isEmpty {
                stk2.append(stk1.removeLast())
            }
        }
    }
}

/**
 * Your MyQueue object will be instantiated and called as such:
 * let obj = new MyQueue();
 * obj.push(x);
 * let param_2 = obj.pop();
 * let param_3 = obj.peek();
 * var myValue : Bool
 * myValue = obj.empty();
 */

评论