【LeetCode题目详解】(四)20.有效的括号、225.用队列实现栈

news2024/11/23 7:59:50

目录

一、力扣第20题:有效的括号

1.解题思路

2.写出代码

3.完整代码

 二、力扣第225题:用队列实现栈

1.思路分析

2.代码实现

3.完整代码

总结


一、力扣第20题:有效的括号

题目链接:20. 有效的括号 - 力扣(Leetcode)

题目描述:

1.解题思路

我们先分析一下题目,它一共只需要匹配三种情况,() [] {}。对于字符串的的一堆括号,我们其实可以将它想象成一共栈,当字符串是( [ { 也就是左括号的时候,就入栈。当遇到右括号的时候,我们就看这个右括号是否与栈顶元素匹配,顺便把栈顶元素给取出来。如果刚好匹配,那太好了,我们可以看下一个字符,是需要入栈还是需要进行匹配。我们进行重复判断,当刚好栈为空的时候,那么也就是说明这个字符串匹配成功了。如果不匹配的话,那我们直接返回false就可以了。

2.写出代码

我们的思路全部是利用栈的,所以我们必须得先实现一个栈出来。根据我们这些思路,我们需要使用的栈操作有初始化栈、入栈、销毁栈、判断栈是否为空、取出栈顶的元素、出栈这些操作。我们先来实现一下这些操作。

如下所示,因为该题是接口型的,所以我们无需写出头文件,这是我们栈的实现。注意这里一定要自己写出来

typedef char STDateType;
typedef struct Stack
{
    STDateType* a;
    int top;
    int capacity;
}Stack;
//初始化栈
void StackInit(Stack* ps)
{
    assert(ps);
    STDateType* tmp = (STDateType*)malloc(4*sizeof(STDateType));
    if(tmp==NULL)
    {
        printf("malloc is fail\n");
        exit(-1);
    }
    pa->a=tmp;
    ps->top=0;
    ps->capacity=4;
}
//入栈
void StackPush(Stack* ps,STDateType x)
{
    assert(ps);
    //判断容量是否满了
    if(ps->top==ps->capacity)
    {
        //扩容
        STDateType* tmp=(STDateType*)realloc(ps->a,2 * sizeof(STDateType)* ps->capacity);
        if(tmp==NULL)
        {
            printf("realloc is fail\n");
            exit(-1);
        }
        ps->a=tmp;
        ps->capacity*=2;
    }
    //入栈
    ps->a[ps->top]=x;
    ps->top++;
}
//出栈
void StackPop(Stack* ps)
{
    assert(ps);
    assert(ps->top>0);
    ps->top--;
}
//取出栈顶元素
STDateType StackTop(Stack* ps)
{
    assert(ps);
    assert(ps->top>0);
    return ps->a[ps->top-1];
}
//判断栈是否为空
bool StackEmpty(Stack* ps)
{
    assert(ps);
    return ps->top==0;
}
//销毁栈
void StackDestory(Stack* ps)
{
    assert(ps);
    free(ps->a);
    ps->a=NULL;
    ps->capacity=ps->top=0;
}

然后接下来就是我们要开始使用栈了

使用栈的话,要特别注意几个极端情况,如只有左括号,只有右括号,等情况的处理

bool isValid(char * s)
{
    Stack ST;
    StackInit(&ST);
    while(*s)
    {
        switch(*s)
        {
            case '(':
            case '[':
            case '{':
                StackPush(&ST,*s);
                break;
            case ')':
            case ']':
            case '}':
            {
                if(StackEmpty(&ST))
                {
                    StackDestory(&ST);
                    return false;
                }
                char tmp=StackTop(&ST);
                StackPop(&ST);
                if( *s==')'&& tmp!='('||
                    *s==']'&& tmp!='['||
                    *s=='}'&& tmp!='{')
                {
                    StackDestory(&ST);
                    return false;
                }
                break;
            }
            default:
                break;
        }
        s++;
    }
    if(!StackEmpty(&ST))
    {
        StackDestory(&ST);
        return false;
    }
    else
    {
        StackDestory(&ST);
        return true;
    }
}

3.完整代码

typedef char STDateType;
typedef struct Stack
{
    STDateType* a;
    int top;
    int capacity;
}Stack;
//初始化栈
void StackInit(Stack* ps)
{
    assert(ps);
    STDateType* tmp = (STDateType*)malloc(4*sizeof(STDateType));
    if(tmp==NULL)
    {
        printf("malloc is fail\n");
        exit(-1);
    }
    ps->a=tmp;
    ps->top=0;
    ps->capacity=4;
}
//入栈
void StackPush(Stack* ps,STDateType x)
{
    assert(ps);
    //判断容量是否满了
    if(ps->top==ps->capacity)
    {
        //扩容
        STDateType* tmp=(STDateType*)realloc(ps->a,2 * sizeof(STDateType)* ps->capacity);
        if(tmp==NULL)
        {
            printf("realloc is fail\n");
            exit(-1);
        }
        ps->a=tmp;
        ps->capacity*=2;
    }
    //入栈
    ps->a[ps->top]=x;
    ps->top++;
}
//出栈
void StackPop(Stack* ps)
{
    assert(ps);
    assert(ps->top>0);
    ps->top--;
}
//取出栈顶元素
STDateType StackTop(Stack* ps)
{
    assert(ps);
    assert(ps->top>0);
    return ps->a[ps->top-1];
}
//判断栈是否为空
bool StackEmpty(Stack* ps)
{
    assert(ps);
    return ps->top==0;
}
//销毁栈
void StackDestory(Stack* ps)
{
    assert(ps);
    free(ps->a);
    ps->a=NULL;
    ps->capacity=ps->top=0;
}
bool isValid(char * s)
{
    Stack ST;
    StackInit(&ST);
    while(*s)
    {
        switch(*s)
        {
            case '(':
            case '[':
            case '{':
                StackPush(&ST,*s);
                break;
            case ')':
            case ']':
            case '}':
            {
                if(StackEmpty(&ST))
                {
                    StackDestory(&ST);
                    return false;
                }
                char tmp=StackTop(&ST);
                StackPop(&ST);
                if( *s==')'&& tmp!='('||
                    *s==']'&& tmp!='['||
                    *s=='}'&& tmp!='{')
                {
                    StackDestory(&ST);
                    return false;
                }
                break;
            }
            default:
                break;
        }
        s++;
    }
    if(!StackEmpty(&ST))
    {
        StackDestory(&ST);
        return false;
    }
    else
    {
        StackDestory(&ST);
        return true;
    }
}

 二、力扣第225题:用队列实现栈

题目链接:225. 用队列实现栈 - 力扣(Leetcode)

题目描述:

 

1.思路分析

我们现在有两个队列,队列的性质是先进先出,而栈的性质是先进后出。那么我们该如何实现呢?我们可以这样做,假如说这是两个队列,我们先将数据都放入一个队列中

当我们想要出去一共数据的时候,那么栈的性质是先出4。所以我们可以先将1 2 3都放入第二个队列中,然后4就可以出去了。

 当我们想要插入一共数据的时候,我们直接插入到有数据的一个队列中,这样就能模拟对栈的性质了。

2.代码实现

既然要运用到队列,那么我们得先实现一下队列。才可以去使用

如下所示,是本题的队列的实现部分

typedef int QDateType;
typedef struct QNode
{
    struct QNode* next;
    QDateType date;
}QNode;
typedef struct Queue
{
    QNode* head;
    QNode* tail;
}Queue;
//队列的初始化
void QueueInit(Queue* pq)
{
    assert(pq);
    pq->head=NULL;
    Pq->tail=NULL;
}
//队列的插入
void QueuePush(Queue* pq,QDateType x)
{
    assert(pq);
    //创建结点
    QNode* newnode=(QNode*)malloc(sizeof(QNode));
    if(newnode==NULL)
    {
        printf("malloc is fail\n");
        exit(-1);
    }
    newnode->next=NULL;
    newnode->date=x;
    //第一个结点的插入
    if(pq->head==NULL)
    {
        pq->head=pq->tail=newnode;
    }
    //非第一个结点的插入
    else
    {
        pq->tail->next=newnode;
        pq->tail=newnode;
    }
}
//出队列
void QueuePop(Queue* pq)
{
    assert(pq);
    assert(pq->head);
    //如果只有一个结点,那么tail会形成野指针
    if(pq->head->next==NULL)
    {
        free(pq->head);
        pq->head=pq->tail=NULL;
    }
    else
    {
        QNode* second=pq->head->next;
        free(pq->head);
        pq->head=second;
    }
}
//队头的元素
QDateType QueueFront(Queue* pq)
{
    assert(pq);
    assert(pq->head);
    return pq->head->date;
}
//队尾的元素
QDateType QueueBack(Queue* pq)
{
    assert(pq);
    assert(pq->head);
    return pq->tail->date;
}
//队列的元素个数
int QueueSize(Queue* pq)
{
    assert(pq);
    int size=0;
    QNode* cur=pq->head;
    while(cur)
    {
        size++;
        cur=cur->next;
    }
    return size;
}
//队列是否为空
bool QueueEmpty(Queue* pq)
{
    assert(pq);
    return pq->head==NULL;
}
//队列的销毁
void QueueDestory(Queue* pq)
{
    assert(pq);
    QNode* cur=pq->head;
    while(cur)
    {
        QNode* next=cur->next;
        free(cur);
        cur=next;
    }
    pq->head=NULL;
    pq->tail=NULL;
}

有了这个队列,我们才可以去完成这道题。


typedef struct {
    Queue q1;
    Queue q2;
} MyStack;


MyStack* myStackCreate() {
    MyStack* ps=(MyStack*)malloc(sizeof(MyStack));
    if(ps==NULL)
    {
        printf("malloc is fail\n");
        exit(-1);
    }
    //初始化队列
    QueueInit(&ps->q1);
    QueueInit(&ps->q2);
    return ps;
}

void myStackPush(MyStack* obj, int x) {
    if(QueueEmpty(&obj->q1))
    {
        QueuePush(&obj->q2,x);
    }
    else
    {
        QueuePush(&obj->q1,x);
    }
}

int myStackPop(MyStack* obj) {
    Queue* emptyQueue=&obj->q1;
    Queue* noemptyQueue=&obj->q2;
    if(!QueueEmpty(&obj->q1))
    {
        emptyQueue=&obj->q2;
        noemptyQueue=&obj->q1;
    }
    while(QueueSize(noemptyQueue) >1)
    {
        QueuePush(emptyQueue,QueueFront(noemptyQueue));
        QueuePop(noemptyQueue);
    }
    int ret=QueueFront(noemptyQueue);
    QueuePop(noemptyQueue);
    return ret;
}

int myStackTop(MyStack* obj) {
    if(!QueueEmpty(&obj->q1))
    {
        return QueueBack(&obj->q1);
    }
    else
    {
        return QueueBack(&obj->q2);
    }
}

bool myStackEmpty(MyStack* obj) {
    if(QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2))
    {
        return true;
    }
    else
    {
        return false;
    }
}

void myStackFree(MyStack* obj) {
    QueueDestory(&obj->q1);
    QueueDestory(&obj->q2);
    free(obj);

}

3.完整代码

typedef int QDateType;
typedef struct QNode
{
    struct QNode* next;
    QDateType date;
}QNode;
typedef struct Queue
{
    QNode* head;
    QNode* tail;
}Queue;
//队列的初始化
void QueueInit(Queue* pq)
{
    assert(pq);
    pq->head=NULL;
    pq->tail=NULL;
}
//队列的插入
void QueuePush(Queue* pq,QDateType x)
{
    assert(pq);
    //创建结点
    QNode* newnode=(QNode*)malloc(sizeof(QNode));
    if(newnode==NULL)
    {
        printf("malloc is fail\n");
        exit(-1);
    }
    newnode->next=NULL;
    newnode->date=x;
    //第一个结点的插入
    if(pq->head==NULL)
    {
        pq->head=pq->tail=newnode;
    }
    //非第一个结点的插入
    else
    {
        pq->tail->next=newnode;
        pq->tail=newnode;
    }
}
//出队列
void QueuePop(Queue* pq)
{
    assert(pq);
    assert(pq->head);
    //如果只有一个结点,那么tail会形成野指针
    if(pq->head->next==NULL)
    {
        free(pq->head);
        pq->head=pq->tail=NULL;
    }
    else
    {
        QNode* second=pq->head->next;
        free(pq->head);
        pq->head=second;
    }
}
//队头的元素
QDateType QueueFront(Queue* pq)
{
    assert(pq);
    assert(pq->head);
    return pq->head->date;
}
//队尾的元素
QDateType QueueBack(Queue* pq)
{
    assert(pq);
    assert(pq->head);
    return pq->tail->date;
}
//队列的元素个数
int QueueSize(Queue* pq)
{
    assert(pq);
    int size=0;
    QNode* cur=pq->head;
    while(cur)
    {
        size++;
        cur=cur->next;
    }
    return size;
}
//队列是否为空
bool QueueEmpty(Queue* pq)
{
    assert(pq);
    return pq->head==NULL;
}
//队列的销毁
void QueueDestory(Queue* pq)
{
    assert(pq);
    QNode* cur=pq->head;
    while(cur)
    {
        QNode* next=cur->next;
        free(cur);
        cur=next;
    }
    pq->head=NULL;
    pq->tail=NULL;
}


typedef struct {
    Queue q1;
    Queue q2;
} MyStack;


MyStack* myStackCreate() {
    MyStack* ps=(MyStack*)malloc(sizeof(MyStack));
    if(ps==NULL)
    {
        printf("malloc is fail\n");
        exit(-1);
    }
    //初始化队列
    QueueInit(&ps->q1);
    QueueInit(&ps->q2);
    return ps;
}

void myStackPush(MyStack* obj, int x) {
    if(QueueEmpty(&obj->q1))
    {
        QueuePush(&obj->q2,x);
    }
    else
    {
        QueuePush(&obj->q1,x);
    }
}

int myStackPop(MyStack* obj) {
    Queue* emptyQueue=&obj->q1;
    Queue* noemptyQueue=&obj->q2;
    if(!QueueEmpty(&obj->q1))
    {
        emptyQueue=&obj->q2;
        noemptyQueue=&obj->q1;
    }
    while(QueueSize(noemptyQueue) >1)
    {
        QueuePush(emptyQueue,QueueFront(noemptyQueue));
        QueuePop(noemptyQueue);
    }
    int ret=QueueFront(noemptyQueue);
    QueuePop(noemptyQueue);
    return ret;
}

int myStackTop(MyStack* obj) {
    if(!QueueEmpty(&obj->q1))
    {
        return QueueBack(&obj->q1);
    }
    else
    {
        return QueueBack(&obj->q2);
    }
}

bool myStackEmpty(MyStack* obj) {
    if(QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2))
    {
        return true;
    }
    else
    {
        return false;
    }
}

void myStackFree(MyStack* obj) {
    QueueDestory(&obj->q1);
    QueueDestory(&obj->q2);
    free(obj);

}

/**
 * Your MyStack struct will be instantiated and called as such:
 * MyStack* obj = myStackCreate();
 * myStackPush(obj, x);
 
 * int param_2 = myStackPop(obj);
 
 * int param_3 = myStackTop(obj);
 
 * bool param_4 = myStackEmpty(obj);
 
 * myStackFree(obj);
*/

总结

本小节完成了两道力扣题,20.有效的括号、225.用队列实现栈

如果对你有帮助的话,不要忘记一键三连哦!!!

想获得更多优质的内容,一定要关注我哦!!!

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

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

相关文章

计算机毕设Python+Vue学生寝室管理系统(程序+LW+部署)

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

哈夫曼树的构造及应用

哈夫曼树的构造及应用 文章目录哈夫曼树的构造及应用带权路径长度哈夫曼树定义哈夫曼树的性质:构造哈夫曼树构造哈夫曼树存储及生成算法算法框架代码实操:应用: 哈夫曼编码带权路径长度 设二叉树具有n个带权值的叶子节点,那么从根节点到各个叶子节点的路径长度与相应…

【图像分割】模糊聚类算法FCM图像分割【含Matlab源码 084期】

⛄一、模糊聚类算法FCM简介 1 前言 图像分割是图像进行后续分析处理的基础,它将图像分成不同特征部分并获得所需目标,广泛应用于诸多领域.彩色多目标图像具有更为丰富的图像信息,目标色彩较多,且同一色彩的目标有时具…

统计学习方法 | 感知机

感知机是二类分类的线性分类模型,其输入为实例的特征向量,输出为实例的类别,取1和-1二值 感知机对应于输入空间(特征空间)中将实例划分为正负两类的分离超平面,属于判别模型 一.模型介绍和学习策略 1.模…

牛客题霸sql入门篇之多表查询

牛客题霸sql入门篇之多表查询 1 子查询 1.1 浙江大学用户题目回答情况 1.1.1 题目内容 a 内容1 b 内容2 1.1.2 示例代码 SELECT device_id,question_id,result FROM question_practice_detail WHERE device_id(SELECT device_id FROM user_profile WHERE university浙江大…

[附源码]计算机毕业设计Python的个人理财系统(程序+源码+LW文档)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置: Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术: django python Vue 等等组成,B/S模式 pychram管理等…

pyqt 搭建深度学习训练界面(二)

炼丹软件 github链接: 有需要联系我 requirements: 测试在ubuntu18.04和Windows均可运行 ubuntu18.04 OS: Ubuntu 18.04.6 LTS Python version: 3.7 (64-bit runtime) Is CUDA available: True CUDA runtime version: 11.1.74 GPU models and configuration: GPU 0: NVI…

基于云的文档管理软件/文档管理系统(DMS)

基于云的文档管理软件 由于违反法规而导致的安全漏洞、数据丢失、版本管理等难题和诉讼已经变得非常普遍,以至于这一切都感觉像是“正常”的现象。使用文档管理系统,可以让您避免这些麻烦。安全标准的执行、信息的合规性和维护都在控制之中,只…

【人脸识别】SVM和PCA人脸识别【含GUI Matlab源码 369期】

⛄一、简介 1 PCA-SVM原理 1.1 主成分分析PCA 本文处理的所有原始图片都是112x 92大小的pgm格式图片, 每幅图片包含10304个像素点, 每一行代表一个样本,维数就是10304维。维数过大使得数据处理工作十分复杂,同时,图片…

axios传参的语法

请求方式 POST 向服务器新增数据 GET 从服务器获取数据 DELETE 删除服务器上的数据 PUT 更新服务器上的数据(侧重于完整更新:例如更新用户的完整信息) PATCH 更新服务器上的数据(侧重于部分更新:例如只更新用户的手机号 ) get axios({url: 请求地址,m…

制作自已的屏保动态

制作自已的屏保动态我的环境第一步:编写自己的屏保程序1、代码准备2、编译第二步:有了可运行程序,使用RAR压缩工具将资源和程序打包成独立可执行exe第三步:将dist.exe配置成系统屏幕保护参考我的环境 win10 python3.X pycharm 第…

Linux学习08-认识与学习BASH

1 认识BASH 我们必须要通过Shell将我们输入的命令与内核沟通,好让内核可以控制硬件来正确无误地工作。 Bash shell的功能 历史命令:命令行按“上下键”就可以找到前/后一个输入的指令。 命令与文件补全功能: [Tab] 接在一串指令的第一个…

大学生学习网站哪里找?收好这15个网站

1.学堂在线 地址:https://www.xuetangx.com/ 这里面的课程都是精选,以北大清华为首的高校汇聚于此 2.中国大学生MOOC 地址:https://www.icourse163.org/ 不多说都是精品 3.网易公开课 地址:https://open.163.com/ 网易公开课汇集清华、北大、哈佛、耶鲁等世界名…

全景分割~

Hinton组提出基于大型全景掩码的实例分割框架,图像视频场景丝滑切换 全景分割是一项基本的视觉任务,该任务旨在为图像的每个像素指定语义标签和实例标签。语义标签描述每个像素的类别(例如天空、竖直物体等),实例标签…

408 | 考前知识拾遗

计网 二、物理层 各种编码图像 数据交换方式——怎么算时间 VLAN每个VLAN都是一个广播域 三、数据链路层 差错控制:检错、纠错 停等、GBN、SR差别 随机访问 VLAN的考点 交换机:转发、自学习 四、网错层 路由协议/算法 ☆☆☆IPV4分组 1、网关配置、路由…

JVM——常量池

目录一、常量池二、运行时常量池三、intern方法 1.8四、intern方法 1.6五、StringTable 垃圾回收六、StringTable调优通过解决以下问题可以更深入了解字符串创建过程中的原理 一、常量池 二进制字节码的组成:类的基本信息、常量池、类的方法定义(包含…

集合的框架体系和Collection接口

1.集合的理解和好处 前面我们保存多个数据使用的是数组,那么数组有不足的地方,我们分析一下 1.1数组 1)长度开始时必须指定,而且一旦指定,不能更改 2)保存的必须为同一类型的元素 3)使用数组进行增加/删除元素的示例代码-比较麻烦…

调试3D渲染和3D可视化的五个好处

建筑和建筑环境是我们日常生活中不可避免的一部分,直接影响我们和我们的福祉。它可以是我们的家、办公室、附近的教堂或城市的商业综合体;所有这一切的设计和规划都是建筑。然而,具有讽刺意味的是,建筑的交流往往并不具有包容性。例如&#x…

玩以太坊链上项目的必备技能(函数及其可见性和状态可变性-Solidity之旅十三)

状态变量可见性 在这之前的文章里,给出的例子中,声明的状态变量都修饰为public,因为我们将状态变量声明为public后,Solidity 编译器自动会为我们生成一个与状态变量同名的、且函数可见性为public的函数! 在 Solidity…

ASP.NET Core 3.1系列(19)——EFCore中的添加实体操作

1、前言 前面介绍了EFCore中关于查询和执行原生SQL的操作,这篇博客就来介绍一下EFCore中添加实体的相关操作。关于添加实体,EFCore提供了多种方法供开发者使用。但EFCore中针对实体的一系列操作最终都会被转换成SQL,因此这些方法之间也存在着…