【LeetCode刷题日志】225.用队列实现栈

news2025/4/11 14:07:35

  • 🎈个人主页:库库的里昂
  •  🎐C/C++领域新星创作者
  •  🎉欢迎 👍点赞✍评论⭐收藏
  • ✨收录专栏:LeetCode 刷题日志
  • 🤝希望作者的文章能对你有所帮助,有不足的地方请在评论区留言指正,大家一起学习交流!🤗

目录

1.题目描述

2.解题思路+代码实现

方法一:两个队列

思路及算法:

代码实现:

方法二:一个队列

思路及算法:

代码实现:


1.题目描述

OJ链接 【leetcode 题号:225.用队列实现栈】【难度:简单】

请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(pushtoppop 和 empty)。

实现 MyStack 类:

  • void push(int x) 将元素 x 压入栈顶。
  • int pop() 移除并返回栈顶元素。
  • int top() 返回栈顶元素。
  • boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。

注意:

  • 你只能使用队列的基本操作 —— 也就是 push to backpeek/pop from frontsize 和 is empty 这些操作。
  • 你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。

示例:

输入:
["MyStack", "push", "push", "top", "pop", "empty"]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 2, 2, false]

解释:
MyStack myStack = new MyStack();
myStack.push(1);
myStack.push(2);
myStack.top(); // 返回 2
myStack.pop(); // 返回 2
myStack.empty(); // 返回 False

提示:

  • 1 <= x <= 9
  • 最多调用100 次 pushpoptop 和 empty
  • 每次调用 pop 和 top 都保证栈不为空

进阶:你能否仅用一个队列来实现栈。

2.解题思路+代码实现

方法一:两个队列
思路及算法:

为了满足栈的特性,即最后入栈的元素最先出栈,在使用队列实现栈时,应满足队列前端的元素是最后入栈的元素。可以使用两个队列实现栈的操作,其中q1用于存储栈内的元素,q2作为入栈操作的辅助队列。

入栈操作时,首先将元素入队到q2,然后将q1的全部元素依次出队并入队列q2 ,此时q2的前端的元素即为新入栈的元素,再将q1和q2互换,则q1的元素即为栈内的元素,q1的前端和后端分别对应栈顶和栈底。

由于每次入栈操作都确保q1的前端元素为栈顶元素,因此出栈操作和获得栈顶元素操作都可以简单实现。出栈操作只需要移除q1的前端元素并返回即可,获得栈顶元素操作只需要获得q1的前端元素并返回即可(不移除元素)。

由于q1用于存储栈内的元素,判断栈是否为空时,只需要判断q1是否为空即可。

代码实现:
typedef int QDataType;
typedef struct QueueNode
{
    struct QueueNode* next;
    QDataType data;
}QNode;
 
typedef struct Queue
{
    QNode* phead;
    QNode* ptail;
    int size;
}Queue;
 
void QueueInit(Queue* pq)
{
    assert(pq);
    pq->phead = NULL;
    pq->ptail = NULL;
    pq->size = 0;
}
void QueueDestroy(Queue* pq)
{
    assert(pq);
    QNode* cur = pq->phead;
    while (cur) {
        QNode* next = cur->next;
        free(cur);
        cur = next;
    }
    pq->phead = pq->ptail = NULL;
    pq->size = 0;
}
void QueuePush(Queue* pq, QDataType x)
{
    assert(pq);
    QNode* newnode = (QNode*)malloc(sizeof(QNode));
    if (newnode == NULL) {
        perror("mallloc fail\n");
        return;
    }
    newnode->data = x;
    newnode->next = NULL;
    if (pq->ptail == NULL) {
        assert(pq->phead == NULL);
        pq->phead = pq->ptail = newnode;
    }
    else {
        pq->ptail->next = newnode;
        pq->ptail = newnode;
    }
    pq->size++;
}
bool QueueEmpty(Queue* pq)
{
    assert(pq);
    return pq->size == 0;
}
void QueuePop(Queue* pq)
{
    assert(pq);
    assert(!QueueEmpty(pq));
    if (pq->phead->next == NULL) {
        free(pq->phead);
        pq->phead = pq->ptail = NULL;
    }
    else {
        QNode* next = pq->phead->next;
        free(pq->phead);
        pq->phead = next;
    }
    pq->size--;
}
QDataType QueueFront(Queue* pq)
{
    assert(pq);
    assert(!QueueEmpty(pq));
    return pq->phead->data;
}
QDataType QueueBack(Queue* pq)
{
    assert(pq);
    assert(!QueueEmpty(pq));
    return pq->ptail->data;
}
int QueueSize(Queue* pq)
{
    assert(pq);
    return pq->size;
}
 
//------以下为OJ提供-------
 
typedef struct {
    Queue q1;
    Queue q2;
} MyStack;
 
MyStack* myStackCreate() {
    MyStack* obj = (MyStack*)malloc(sizeof(MyStack));
    if (obj == NULL) {
        perror("malloc fail");
        return NULL;
    }
    QueueInit(&obj->q1);
    QueueInit(&obj->q2);
    return obj;
}
 
void myStackPush(MyStack* obj, int x) {
    if (!QueueEmpty(&obj->q1)) {
        QueuePush(&obj->q1, x);
    }
    else {
        QueuePush(&obj->q2, x);
    }
}
 
int myStackPop(MyStack* obj) {
    Queue* pEmptyQ = &obj->q1;
    Queue* pNonEmptyQ = &obj->q2;
    if (!QueueEmpty(&obj->q1)) {
        pEmptyQ = &obj->q2;
        pNonEmptyQ = &obj->q1;
    }
    while (QueueSize(pNonEmptyQ) > 1) {
        QueuePush(pEmptyQ, QueueFront(pNonEmptyQ));
        QueuePop(pNonEmptyQ);
    }
    int top = QueueFront(pNonEmptyQ);
    QueuePop(pNonEmptyQ);
    return top;
}
 
int myStackTop(MyStack* obj) {
    if (!QueueEmpty(&obj->q1)) {
        return QueueBack(&obj->q1);
    }
    else {
        return QueueBack(&obj->q2);
    }
}
 
bool myStackEmpty(MyStack* obj) {
    return QueueEmpty(&obj->q1) &&
        QueueEmpty(&obj->q2);
}
 
void myStackFree(MyStack* obj) {
    QueueDestroy(&obj->q1);
    QueueDestroy(&obj->q2);
    free(obj);
}

复杂度分析

  • 时间复杂度:入栈操作O(n),其余操作都是O(1),其中n是栈内的元素个数。 入栈操作需要将q1中的n个元素出队,并入队n+1个元素到q2,共有2n+1次操作,每次出队和入队操作的时间复杂度都是O(1),因此入栈操作的时间复杂度是 O(n)。 出栈操作对应将q1的前端元素出队,时间复杂度是 O(1)。 获得栈顶元素操作对应获得q1的前端元素,时间复杂度是O(1)。 判断栈是否为空操作只需要判断q1是否为空,时间复杂度是 O(1)。
  • 空间复杂度:O(n),其中n是栈内的元素个数。需要使用两个队列存储栈内的元素。
方法二:一个队列
思路及算法:

方法一使用了两个队列实现栈的操作,也可以使用一个队列实现栈的操作。

使用一个队列时,为了满足栈的特性,即最后入栈的元素最先出栈,同样需要满足队列前端的元素是最后入栈的元素。

入栈操作时,首先获得入栈前的元素个数 nnn,然后将元素入队到队列,再将队列中的前n个元素(即除了新入栈的元素之外的全部元素)依次出队并入队到队列,此时队列的前端的元素即为新入栈的元素,且队列的前端和后端分别对应栈顶和栈底。

由于每次入栈操作都确保队列的前端元素为栈顶元素,因此出栈操作和获得栈顶元素操作都可以简单实现。出栈操作只需要移除队列的前端元素并返回即可,获得栈顶元素操作只需要获得队列的前端元素并返回即可(不移除元素)。

由于队列用于存储栈内的元素,判断栈是否为空时,只需要判断队列是否为空即可。

代码实现:
typedef struct tagListNode {
    struct tagListNode* next;
    int val;
} ListNode;

typedef struct {
    ListNode* top;
} MyStack;

MyStack* myStackCreate() {
    MyStack* stk = calloc(1, sizeof(MyStack));
    return stk;
}

void myStackPush(MyStack* obj, int x) {
    ListNode* node = malloc(sizeof(ListNode));
    node->val = x;
    node->next = obj->top;
    obj->top = node;
}

int myStackPop(MyStack* obj) {
    ListNode* node = obj->top;
    int val = node->val;
    obj->top = node->next;
    free(node);

    return val;
}

int myStackTop(MyStack* obj) {
    return obj->top->val;
}

bool myStackEmpty(MyStack* obj) {
    return (obj->top == NULL);
}

void myStackFree(MyStack* obj) {
    while (obj->top != NULL) {
        ListNode* node = obj->top;
        obj->top = obj->top->next;
        free(node);
    }
    free(obj);
}

复杂度分析

  • 时间复杂度:入栈操作O(n),其余操作都是O(1),其中n是栈内的元素个数。 入栈操作需要将队列中的n个元素出队,并入队n+1个元素到队列,共有2n+1次操作,每次出队和入队操作的时间复杂度都是O(1),因此入栈操作的时间复杂度是O(n)。 出栈操作对应将队列的前端元素出队,时间复杂度是O(1)。获得栈顶元素操作对应获得队列的前端元素,时间复杂度是O(1)。 判断栈是否为空操作只需要判断队列是否为空,时间复杂度是O(1)。
  • 空间复杂度:O(n),其中n是栈内的元素个数。需要使用一个队列存储栈内的元素。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1224837.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Git配置代理:fatal: unable to access*** github Failure when receiving data from

~吐槽一下 github自从被微软收购以后&#xff0c;大多数情况没点科技上网都进不去了&#xff0c;还是怀念以前随时访问的时光。 我一直都是开着系统代理的&#xff0c;但是今天拉一个项目发现拉不下来了&#xff0c;报错&#xff1a; fatal: unable to access https://githu…

人工智能基础_机器学习044_逻辑回归代码实现与手动计算概率---人工智能工作笔记0084

上面我们已经把逻辑回归的公式,以及,公式对应的图形都画画出来了,然后我们再来看看 如何用代码实现 可以看到上面是代码,咱们自己去写一下 import numpy as np from sklearn.linear_model import LogistieRegression from sklearn import datasets # 训练数据和测试数据拆分…

浅析AcrelEMS-CIA机场智慧能源管平台解决方案-安科瑞 蒋静

1 概述 机场智慧能源管平台解决方案对机场范围内变电站内的高低压配电设备 、 发电机、变压器 、UPS、EPS 、广场照明 、 室内照明 、通风及排水等机电设备进行实时分布式监控和集中管理 , 实现无人值守 , 确保高速公路安全畅通 , 提高 自动化管理水平 , 降低机电设备的运行维…

联想笔记本电脑触摸板失灵了怎么办

这里写自定义目录标题 thinkbook笔记本电脑触摸板失灵 thinkbook笔记本电脑触摸板失灵 由于重装系统&#xff0c;导致笔记本的触控板失灵&#xff0c; 网上说的办法有 1、按键盘上的ctrlf6键&#xff0c;打开触控板功能&#xff1a;无效 2、设置——>设备——>触控板&am…

buuctf-web-p6 [NPUCTF2020]web 狗

java: HelloWorld.class import java.io.PrintStream;public class HelloWorld {public static void main(String[] paramArrayOfString){System.out.println("众所周知&#xff0c;你是一名WEB选手&#xff0c;掌握javaweb也是一项必备技能&#xff0c;那么逆向个java应…

央企太卷.....来自央企的7个面试题,一个一个生产难题

说在前面 在40岁老架构师尼恩的&#xff08;50&#xff09;读者社群中&#xff0c;最近小伙伴&#xff0c;面试央企、美团、京东、阿里、 百度、头条等大厂。 下面是一个小伙伴成功拿到通过了一个央企设计研究院一面面试&#xff0c;现在把面试真题和参考答案收入咱们的宝典。…

Git企业开发级讲解(五)

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、bug 分⽀二、删除临时分支三、小结 一、bug 分⽀ 假如我们现在正在 dev2 分⽀上进⾏开发…

LeetCode994.腐烂的橘子

看完题我觉得这不是和上一道岛屿的题一样简单嘛&#xff0c;然后写了将近2个小时才写出来&#xff0c;我的思路就是&#xff0c;用check()先对grid检查一下&#xff0c;是否有以下情况&#xff1a; &#xff08;如果有1的周围都是空&#xff0c;则这个位置用不腐烂&#xff0c;…

清华学霸告诉你:如何自学人工智能?

清华大学作为中国顶尖的学府之一&#xff0c;培养了许多优秀的人才&#xff0c;其中不乏在人工智能领域有所成就的学霸。通过一位清华学霸的经验分享&#xff0c;揭示如何自学人工智能&#xff0c;帮助你在这场科技浪潮中勇往直前。 一、夯实基础知识 数学基础&#xff1a;学习…

【Qt开发流程】之HelloWorld程序

【Qt开发流程】之HelloWorld程序 目的编写程序新建项目文件说明及界面设计 程序运行及发布程序运行程序发布手动构建使用windeployqt进行构建 设置应用程序图标修改快捷键类型列表命令行编译程序命令行编译.ui文件自定义类项目模式及项目文件介绍项目模式项目文件 目的 从Hell…

vue --version无法显示,只弹出vs窗口

参考连接&#xff1a; nodejs环境配置&#xff08;解压包&#xff09;安装教程_nodejs解压版安装及环境配置_tubond的博客-CSDN博客 原因&#xff1a;环境没搞好&#xff0c;没有设置全局文件夹&#xff0c;node默认放在C盘了&#xff0c;C盘有权限。因为npm -i vue/cli创建…

2023最新最全【OpenMV】 入门教程

1. 什么是OpenMV OpenMV 是一个开源&#xff0c;低成本&#xff0c;功能强大的 机器视觉模块。 OpenMV上的机器视觉算法包括 寻找色块、人脸检测、眼球跟踪、边缘检测、标志跟踪 等。 以STM32F427CPU为核心&#xff0c;集成了OV7725摄像头芯片&#xff0c;在小巧的硬件模块上&a…

电磁场与电磁波part4--时变电磁场

1、采用洛伦兹条件使得矢量位 与标量位 分离在两个独立的方程中&#xff0c;且矢量位 仅与电流密度 有关&#xff0c;而标量位 仅与电荷密度 有关。 2、电磁能量守恒定理&#xff08;坡印廷定理&#xff09; 即减少的电磁能量电磁场所做的功流出的电磁能量 3、设u(r,t)是…

单元测试实战(四)MyBatis-Plus 的测试

为鼓励单元测试&#xff0c;特分门别类示例各种组件的测试代码并进行解说&#xff0c;供开发人员参考。 本文中的测试均基于JUnit5。 单元测试实战&#xff08;一&#xff09;Controller 的测试 单元测试实战&#xff08;二&#xff09;Service 的测试 单元测试实战&am…

Java学习 10.Java-类和对象

一、面向对象的初步认知 1.1 什么是面向对象 面向对象是解决问题的一种思想&#xff0c;主要依靠对象之间的交互完成一件事情&#xff0c;用面向对象的思想来设计程序&#xff0c;更符合人们对事物的认知&#xff0c;对于大型程序的设计、拓展以及维护都非常友好 1.2 面向对…

qtpdfium的编译及读取pdf文件和一些简单操作

qtpdfium是谷歌的一款开源项目&#xff0c;它的内核是基于国内的福昕pdf&#xff0c;许可协议为 BSD 3-Clause&#xff0c;允许用于闭源商业行为 下载 我们可以从git上进行下载&#xff0c;github&#xff0c;如果嫌下载速度慢&#xff0c;可以从csdn进行下载csdn 下载完成之…

在国内购买GPT服务前的一定要注意!!!

本人已经入坑GPT多日&#xff0c;从最开始的应用GPT到现在的自己研发GPT&#xff0c;聊聊我对使用ChatGPT的一些思考&#xff0c;有需要使用GPT的朋友或者正在使用GPT的朋友&#xff0c;一定要看完这篇文章&#xff0c;可能会比较露骨&#xff0c;也算是把国内知识库、AI的套路…

趣学python编程 (二、计算机硬件和用途介绍)

1944年&#xff0c;美籍匈牙利数学家 冯诺依曼 提出计算机基本结构和工作方式的设想&#xff0c;为计算机的诞生和发展提供了理论基础。时至今日&#xff0c;尽管计算机软硬件技术飞速发展&#xff0c;但计算机本身的体系结构并没有明显的突破&#xff0c;当今的计算机仍属于冯…

操作系统(存储管理进程管理设备管理)

文章目录 存储管理页式存储管理概念优点缺点页面置换算法快表&#xff08;很快速的页表&#xff09; 段式存储管理概念优点缺点 段页式存储管理概念优点缺点 进程管理概述作用特征功能分类计算机启动基本流程 进程管理进程的组成进程的基础状态前趋图进程资源图同步和互斥信号量…

【新闻稿】Solv 与 zCloak 联合开发跨境贸易场景下可编程数字凭证项目,获得新加坡、加纳两国央行支持...

关于昨天 Solv 携手 zCloak 与新加坡和加纳两个央行合作的 Project DESFT&#xff0c;很多朋友都发来恭喜和祝福&#xff0c;并希望了解详情。这个事我们秘密努力了半年多&#xff0c;终于有一个阶段性的成果。这里我转载中文版官宣新闻稿&#xff0c;欢迎大家关注。等我忙过这…