[003] [LeetCode刷题记录] 232-用栈实现队列

本文详细介绍了如何使用两个栈来实现一个符合先入先出(FIFO)原则的队列,包括push、pop、peek和empty等操作。在C、C++和Python3中分别给出了实现代码,确保了操作的时间复杂度在平均情况下达到O(1),并且在最坏情况下保持在O(n)。此外,讨论了空间复杂度和不同语言的实现细节,展示了如何利用栈的特性高效地模拟队列操作。
摘要由CSDN通过智能技术生成
LeetCode
刷题记录
题目描述
解题思路及代码
C语言实现
C++语言实现
Python3语言实现

1 题目描述

LeetCode原题链接:232. 用栈实现队列

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):

实现 MyQueue 类:

  • void push(int x) 将元素 x 推到队列的末尾
  • int pop() 从队列的开头移除并返回元素
  • int peek() 返回队列开头的元素
  • boolean empty() 如果队列为空,返回 true ;否则,返回 false

说明:

  • 你只能使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
  • 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。

提示:

  • 1 <= x <= 9
  • 最多调用 100 次 push、pop、peek 和 empty
  • 假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)

2 解题思路及代码

2.1 C语言实现

/**
 * @note
 * 1. 构造两个栈, 一个栈用于入队, 一个栈用于出队
 * 2. 队头指针指向出队栈, 队尾指针指向入队栈(头删尾插)
 * 3. 当出队栈为空时, 将入队栈的数据全部弹出并压入出队栈
 */

// 最多调用100次, 故采用顺序栈
typedef struct{     // 也可用base与top指针构造顺序栈
    int *stk;
    int size;
    int capacity;
}Stack;

Stack* stackCreate(int capacity){
    Stack* ret = (Stack*)malloc(sizeof(Stack));
    ret->stk = malloc(sizeof(int) * capacity);
    ret->size = 0;
    ret->capacity = capacity;
    return ret;
}

void stackPush(Stack* obj, int x){  // 数组容量为测试最大次数, 故无需考虑栈满情况
    if(obj->size < obj->capacity){
        obj->stk[obj->size++] = x;
    }
}

bool isStackEmpty(Stack* obj){
    return obj->size == 0;
}

void stackPop(Stack* obj){      // 弹栈
    obj->size--;
}

int stackTop(Stack* obj){       // 取栈顶元素
    return obj->stk[obj->size - 1];
}

void stackFree(Stack* obj){
    free(obj->stk);
}


typedef struct {
    Stack* front;
    Stack* rear
} MyQueue;


MyQueue* myQueueCreate() {
    MyQueue* ret = (MyQueue*)malloc(sizeof(MyQueue));
    ret->front = stackCreate(100);
    ret->rear = stackCreate(100);
    return ret;
}

void stackInToOut(MyQueue* obj){
    while(!isStackEmpty(obj->rear)){
        stackPush(obj->front, stackTop(obj->rear));
        stackPop(obj->rear);
    }
}

void myQueuePush(MyQueue* obj, int x) {
    stackPush(obj->rear, x);
}

int myQueuePop(MyQueue* obj) {  // 出队(需记录出队元素)
    if(isStackEmpty(obj->front)){
        stackInToOut(obj);
    }
    int x = stackTop(obj->front);
    stackPop(obj->front);
    return x;
}

int myQueuePeek(MyQueue* obj) { // 取队头元素
    if(isStackEmpty(obj->front)){
        stackInToOut(obj);
    }
    return stackTop(obj->front);
}

bool myQueueEmpty(MyQueue* obj) {
    return (isStackEmpty(obj->front) && isStackEmpty(obj->rear));
}

void myQueueFree(MyQueue* obj) {
    stackFree(obj->front);
    stackFree(obj->rear);
}

复杂度分析:

  • 时间复杂度:均摊复杂度 O(1),最坏情况下的时间复杂度 O(n)。
    入队操作每次都将新元素直接压入至入队栈,时间复杂度O(1);出队操作时,当出队栈非空时,直接从栈顶弹出1个元素即可,若为空则需将入队栈n个元素全部弹出并压至出队栈,再从出队栈的栈顶弹出元素,因为出队栈为空出现频率较低,所以均摊后复杂度为O(n)。

  • 空间复杂度:O(n),队列中最多存储n个元素。

2.2 C++语言实现

// 使用stack容器,具体实现思路同C

class MyQueue {
public:
    stack<int> in_stk;  // 入队栈
    stack<int> out_stk; // 出队栈

    MyQueue() {

    }

    void inToOut(){
        if(out_stk.empty()){
            while(!in_stk.empty()){
                out_stk.push(in_stk.top());
                in_stk.pop();
            }
        }
    }

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

    int pop() {
        inToOut();
        int x = out_stk.top();
        out_stk.pop();
        return x;
    }

    int peek() {
        inToOut();
        return out_stk.top();
    }

    bool empty() {
        return in_stk.empty() && out_stk.empty();
    }
};

2.3 Python3语言实现

#解题思路同C,只不过将列表当做栈来使用


class MyQueue:

    def __init__(self):
        self.front = []
        self.rear = []

    def stack_in_out(self):
        if not self.front:
            while self.rear:
                self.front.append(self.rear.pop())

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

    def pop(self) -> int:
        self.stack_in_out()
        return self.front.pop()

    def peek(self) -> int:
        self.stack_in_out()
        if self.front:
            return self.front[-1]
        else:
            return 0

    def empty(self) -> bool:
        return not (bool(self.front) or bool(self.rear))

END

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柯西的彷徨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值