每日一题---OJ题: 有效的括号

片头

嗨! 小伙伴们,大家好! 我们又见面啦! 今天我们来一起尝试一下这道题目---有效的括号,准备好了吗? 我们开始咯!

说实话,我刚开始做这道题的时候也是一脸懵,怎么进行括号匹配呢?

别慌,我们一起画个图,分析分析括号匹配的过程~

如下图所示,上方表示一个字符串数组,存放不同种类的左括号和右括号,用一个指针依次遍历字符串中的每一个元素

如果是左括号,则入栈,如果是右括号,则栈顶元素出栈和字符串数组中的元素进行匹配。

第一次:

左括号,则入栈

第二次:

左括号,则入栈

第三次:

左括号,则入栈

 第四次:

此时指针指向的元素为右括号,应该出栈

第五次:

左括号,则入栈

第六次:

右括号,则出栈

 第七次:

右括号,则出栈

第八次:

右括号,则出栈

第九次:

左括号,则入栈

第十次:

右括号,则出栈

第十一次:

左括号,则入栈

第十二次:

右括号,则出栈

好的,这道题的执行过程我们大致分析清楚了,怎么实现呢?

 我们可以利用栈来解答这道题

先定义Stack.h文件

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int ElemType;
typedef struct Stack {ElemType* arr;		//数组int top;			//栈顶int capacity;		//栈的容量
}Stack;//初始化栈
void StackInit(Stack* ps);
//入栈
void StackPush(Stack* ps,ElemType data);
//出栈
void StackPop(Stack* ps);
//获取栈顶元素
ElemType StackTop(Stack* ps);
//获取栈中有效元素的个数
int StackSize(Stack* ps);
//检测栈是否为空,如果为空返回非零结果,如果不为空返回0
int StackEmpty(Stack* ps);
//销毁栈
void StackDestroy(Stack* ps);

 再定义Stack.c文件

#include"Stack.h"
//初始化栈
void StackInit(Stack* ps) {assert(ps);ps->arr = NULL;ps->capacity = 0;ps->top = 0;
}
//入栈
void StackPush(Stack* ps, ElemType data) {assert(ps);//扩容if (ps->capacity == ps->top) {int newCapacity = ps->capacity == 0 ? 4 : 2 * (ps->capacity);ElemType* temp =(ElemType*) realloc(ps->arr, newCapacity * sizeof(ElemType));if (temp == NULL) {perror("realloc fail!\n");exit(1);}ps->arr = temp;ps->capacity = newCapacity;}ps->arr[ps->top] = data;ps->top++;
}
//出栈
void StackPop(Stack* ps) {assert(ps);assert(!StackEmpty(ps));ps->top--;
}
//获取栈顶元素
ElemType StackTop(Stack* ps) {assert(ps);assert(!StackEmpty(ps));int ret = ps->arr[ps->top - 1];return ret;
}
//获取栈中有效元素的个数
int StackSize(Stack* ps) {assert(ps);return ps->top;
}
//检测栈是否为空,如果为空返回非零结果,如果不为空返回0
int StackEmpty(Stack* ps) {assert(ps);return ps->top == 0;	//如果top为0,说明栈为空,返回1
}
//销毁栈
void StackDestroy(Stack* ps) {assert(ps);if (ps->arr) {free(ps->arr);ps->arr = NULL;}ps->capacity = 0;ps->top = 0;
}

最后我们再来测试一下,定义test.c文件

#include"Stack.h"
#include<stdbool.h>
int main() {Stack st;            //定义一个栈StackInit(&st);      //初始化这个栈StackPush(&st, 1);   //将"1"放入栈内StackPush(&st, 2);   //将"2"放入栈内StackPush(&st, 3);   //将"3"放入栈内StackPush(&st, 4);   //将"4"放入栈内StackPush(&st, 5);   //将"5"放入栈内while (!StackEmpty(&st)) {    //如果栈不为空,那么获取栈中的元素int top = StackTop(&st);   //获取栈顶元素printf("%d ", top);        //打印栈顶元素StackPop(&st);            //将栈顶元素删除}StackDestroy(&st);            //销毁栈return 0;
}

运行结果为:

5   4   3   2   1

 OK啦,我们的栈就实现完毕! 接下来我们就可以将它套用到题目中去~

我们刚写了一个栈,直接把 Stack.h 和 Stack.c 复制粘贴过去,把头文件删掉, 再把 typedef int ElemType 改成 typedef char ElemType;

部分代码如下:

typedef char ElemType;        //一定是 char, 不要弄错了,题目要求是字符串数组
typedef struct Stack {ElemType* arr;		//数组int top;			//栈顶int capacity;		//栈的容量
}Stack;//初始化栈
void StackInit(Stack* ps);
//入栈
void StackPush(Stack* ps,ElemType data);
//出栈
void StackPop(Stack* ps);
//获取栈顶元素
ElemType StackTop(Stack* ps);
//获取栈中有效元素的个数
int StackSize(Stack* ps);
//检测栈是否为空,如果为空返回非零结果,如果不为空返回0
int StackEmpty(Stack* ps);
//销毁栈
void StackDestroy(Stack* ps);//初始化栈
void StackInit(Stack* ps) {ps->arr = NULL;ps->capacity = 0;ps->top = 0;
}
//入栈
void StackPush(Stack* ps, ElemType data) {//扩容if (ps->capacity == ps->top) {int newCapacity = ps->capacity == 0 ? 4 : 2 * (ps->capacity);ElemType* temp =(ElemType*) realloc(ps->arr, newCapacity * sizeof(ElemType));if (temp == NULL) {perror("realloc fail!\n");exit(1);}ps->arr = temp;ps->capacity = newCapacity;}ps->arr[ps->top] = data;    //插入数据ps->top++;                  //栈顶向上移动一个单位
}
//出栈
void StackPop(Stack* ps) {assert(ps);assert(!StackEmpty(ps));    //栈不能为空ps->top--;
}
//获取栈顶元素
ElemType StackTop(Stack* ps) {assert(ps);assert(!StackEmpty(ps));//不改变top指针,只是获取栈顶元素int ret = ps->arr[ps->top - 1];return ret;
}
//获取栈中有效元素的个数
int StackSize(Stack* ps) {assert(ps);return ps->top; //top恰好是元素的个数
}
//检测栈是否为空,如果为空返回非零结果,如果不为空返回0
int StackEmpty(Stack* ps) {return ps->top == 0;
}
//销毁栈
void StackDestroy(Stack* ps) {assert(ps);if (ps->arr) {free(ps->arr);ps->arr = NULL;}ps->capacity = 0;ps->top = 0;
}

 接下来就是重头戏咯! 小伙伴们可要看仔细咯!

第一步,我们先定义一个栈,然后将这个栈初始化

   Stack st;           //定义一个栈StackInit(&st);     //初始化这个栈

第二步,我们用题目所给的条件: 该方法传递过来的形参s, 类型为char* ,意味着s是一个指向字符串数组的指针,可以遍历整个字符串数组, 因此,当s指针遍历到字符串数组的结束符'\0'的时候,退出循环

和刚刚我们分析的思路一样,当s指针遍历到左括号时,则该元素入栈; s指针遍历到右括号时,将栈里面的元素出栈,看是否匹配; 如果匹配不成功,直接返回false; 接着,s指针继续指向下一个元素。

这里有一个特别容易被忽略的一个点: 当栈为空,且遇到右括号,栈里面没有左括号,销毁栈,返回false

这个部分的代码如下:

//当*s不等于'\0'的时候,进入while循环
while(*s){if(*s == '{' || *s == '[' || *s == '('){//将该元素放入栈内StackPush(&st,*s);}else{//当栈为空,且遇到右括号,栈里面没有左括号,返回falseif(StackEmpty(&st)){//销毁栈,防止内存泄漏StackDestroy(&st);return false;}int top = StackTop(&st);        //获取栈顶元素StackPop(&st);                  //将栈顶元素删除//将栈顶元素和*s进行匹配//如果出栈元素是'(',但是此时的*s不是')',说明不匹配,返回false//如果出栈元素是'[',但是此时的*s不是']',说明不匹配,返回false//如果出栈元素是'{',但是此时的*s不是'}',说明不匹配,返回falseif(top == '(' && *s != ')' || top == '[' && *s != ']' || top == '{' && *s != '}')    {    //销毁栈,防止内存泄漏StackDestroy(&st);return false;}}s++;     //s指针继续指向下一个元素
}

哈哈哈,屏幕前的你以为这样代码就写完了吗? 肯定还没有! 因为还有一种情况我们木有考虑到~

那就是当*s已经走到'\0',但是栈不是空,说明栈里面还有左括号,不合题意, 此时StackEmpty返回false ; 如果栈为空,返回true

部分代码如下:

    bool flag = StackEmpty(&st); //用bool类型的flag变量来接受StackEmpty函数的返回值StackDestroy(&st);           //将栈销毁,归还给系统内存return flag;                 //将结果返回

好啦! 这道题被我们解决啦,整体代码如下:

typedef char ElemType;
typedef struct Stack {ElemType* arr;		//数组int top;			//栈顶int capacity;		//栈的容量
}Stack;//初始化栈
void StackInit(Stack* ps);
//入栈
void StackPush(Stack* ps,ElemType data);
//出栈
void StackPop(Stack* ps);
//获取栈顶元素
ElemType StackTop(Stack* ps);
//获取栈中有效元素的个数
int StackSize(Stack* ps);
//检测栈是否为空,如果为空返回非零结果,如果不为空返回0
int StackEmpty(Stack* ps);
//销毁栈
void StackDestroy(Stack* ps);//初始化栈
void StackInit(Stack* ps) {ps->arr = NULL;ps->capacity = 0;ps->top = 0;
}
//入栈
void StackPush(Stack* ps, ElemType data) {//扩容if (ps->capacity == ps->top) {int newCapacity = ps->capacity == 0 ? 4 : 2 * (ps->capacity);ElemType* temp =(ElemType*) realloc(ps->arr, newCapacity * sizeof(ElemType));if (temp == NULL) {perror("realloc fail!\n");exit(1);}ps->arr = temp;ps->capacity = newCapacity;}ps->arr[ps->top] = data;    //插入数据ps->top++;                  //栈顶向上移动一个单位
}
//出栈
void StackPop(Stack* ps) {assert(ps);assert(!StackEmpty(ps));ps->top--;
}
//获取栈顶元素
ElemType StackTop(Stack* ps) {assert(ps);assert(!StackEmpty(ps));//不改变top指针,只是获取栈顶元素int ret = ps->arr[ps->top - 1];return ret;
}
//获取栈中有效元素的个数
int StackSize(Stack* ps) {assert(ps);return ps->top; //top恰好是元素的个数
}
//检测栈是否为空,如果为空返回非零结果,如果不为空返回0
int StackEmpty(Stack* ps) {return ps->top == 0;
}
//销毁栈
void StackDestroy(Stack* ps) {assert(ps);if (ps->arr) {free(ps->arr);ps->arr = NULL;}ps->capacity = 0;ps->top = 0;
}bool isValid(char* s) {Stack st;           //定义一个栈StackInit(&st);     //初始化这个栈//当*s不等于'\0'的时候,进入while循环
while(*s){if(*s == '{' || *s == '[' || *s == '('){//将该元素放入栈内StackPush(&st,*s);}else{//当栈为空,且遇到右括号,栈里面没有左括号,返回falseif(StackEmpty(&st)){//销毁栈,防止内存泄漏StackDestroy(&st);return false;}int top = StackTop(&st);        //获取栈顶元素StackPop(&st);                  //将栈顶元素删除//将栈顶元素和*s进行匹配//如果出栈元素是'(',但是此时的*s不是')',说明不匹配,返回false//如果出栈元素是'[',但是此时的*s不是']',说明不匹配,返回false//如果出栈元素是'{',但是此时的*s不是'}',说明不匹配,返回falseif(top == '(' && *s != ')' || top == '[' && *s != ']' || top == '{' && *s != '}')    {    //销毁栈,防止内存泄漏StackDestroy(&st);return false;}}s++;     //s指针继续指向下一个元素
}bool flag = StackEmpty(&st); //用bool类型的flag变量来接受StackEmpty函数的返回值StackDestroy(&st);           //将栈销毁,归还给系统内存return flag;                 //将结果返回
}

片尾

今天我们学习了一道OJ题---有效的括号,里面包含了栈的一些基础知识,希望看完这篇文章能对友友们有所帮助 !  !  !

点赞收藏加关注 !   !   !

谢谢大家 !   !   !

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

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

相关文章

深入剖析Tomcat(二) 实现一个简单的Servlet容器

现在开始《深入剖析Tomcat》第二章的内容&#xff0c;第一章中&#xff0c;我们编码实现了一个能正常接收HTTP请求并返回静态资源的Web容器&#xff0c;这一章开始引入Servlet的概念&#xff0c;使我们的服务能根据请求动态返回内容。 Servlet是什么&#xff1f; 这是首先要弄…

【系统架构师】-未来信息综合技术

1、信息物理系统技术 CPS是控制系统、嵌入式系统的扩展与延伸&#xff0c;集成感知、计算、通信、控制、和自动控制技术。 构件信息空间中的人、机、物、环境、信息等相互映射、适时交互、高效协同。 体系结构&#xff1a; 1&#xff09;单元级&#xff1a;不可分割的CPS最…

腾讯EdgeOne产品测评体验——开启安全防护,保障数据无忧

当今时代数字化经济蓬勃发展人们的生活逐渐便利&#xff0c;类似线上购物、线上娱乐、线上会议等数字化的服务如雨后春笋般在全国遍地生长&#xff0c;在人们享受这些服务的同时也面临着各式各样的挑战&#xff0c;如网络数据会不稳定、个人隐私容易暴露、资产信息会被攻击等。…

SSRF非常规利用方法

前言 SSRF漏洞在互联网公司中应该是除了越权之外最普遍的漏洞了。关于漏洞的原理&#xff0c;绕过&#xff0c;传统的扫端口、各种探测等利用方式等就不再赘述&#xff0c;这里分享下自己作为攻防当中常用的一些SSRF的利用途径。 0x01 Cloud Metadata 就是各种云上的元数据信…

单链表链表专题

1 链表的概念 概念&#xff1a;链表是⼀种物理存储结构上⾮连续、⾮顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接次序实现的。 链表的结构跟⽕⻋⻋厢相似&#xff0c;淡季时⻋次的⻋厢会相应减少&#xff0c;旺季时⻋次的⻋厢会额外增加⼏节。只 需要…

MySQL表结构的操作

文章目录 1. 创建表2. 查看表3. 修改表4. 删除表 1. 创建表 create table table_name (field1 datatype,field2 datatype,field3 datatype )character set 字符集 collate 校验集 engine 存储引擎;field&#xff1a;列名datatype&#xff1a;列的类型character set&#xff1a…

VueUse工具库 常用api

简介&#xff1a; VueUse不是Vue.use&#xff0c; VueUse 为 Vue 2和Vue3 服务的一套Vue Composition API的常用工具集&#xff0c;&#xff0c;它提供了一系列的 hooks 和工具函数&#xff0c;帮助我们更方便地使用 Vue Composition API。 通俗的来说&#xff0c;这就是一个工…

zookeeper分布式应用程序协调服务+消息中间件kafka分布式数据处理平台

一、zookeeper基本介绍 1.1 zookeeper的概念 Zookeeper是一个开源的分布式的&#xff0c;为分布式框架提供协调服务的Apache项目。 是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件&#xff0c;提供的功能包括&#xff1a;配置维护、域名服务、…

滑动窗口题解2

目录 1 找到字符串中所有字母异位词 分析&#xff1a; 代码展示&#xff1a; 代码展示&#xff1a; 2 串联所有单词的子串 分析&#xff1a; 代码展示&#xff1a; 3 串联所有单词的子串 分析&#xff1a; 代码展示&#xff1a; 4 水果成篮 分析&#xff1a; 代码展…

JDK自带的线程池有哪些?

Java JDK 自带的线程池主要包含以下几种类型&#xff0c;这些线程池都是通过 java.util.concurrent 包中的 Executors 工具类提供的工厂方法创建&#xff1a; 固定大小线程池 (Fixed Thread Pool)&#xff1a; newFixedThreadPool(int nThreads)&#xff1a;创建一个定长线程池…

障碍物识别技术赋能盲人独立出行:一场静默的科技革新

作为一名资深记者&#xff0c;我始终关注并报道那些科技如何助力特殊群体克服生活挑战的动人故事。近期&#xff0c;一款叫做蝙蝠避障的应用进入了我的视线&#xff0c;它搭载先进障碍物识别技术以其独特的优势&#xff0c;悄然为视障人士的独立出行带来了显著变革。 “障碍物识…

一.shell基本知识

目录 1.1为什么学习和使用Shell编程 1.2什么是Shell 1.2.1 shell的起源 1.2.2shell的功能 1.3shell的分类 1.4作为程序设计的语言一—shell 1.5如何学好shell 1.6shell脚本的基本元素 1.7 shell脚本编写规范 1.8 shell脚本的执行方式 1.9 执行脚本的方法 1.10 shel…

ChatGML-6B大模型Windows部署(可CPU运行 保姆级教程)

&#x1f680; 写在最前&#xff1a;这篇文章将学习如何运行ChatGML-6B大模型。 &#x1f680;&#xff1a;点个关注吧&#x1f600;&#xff0c;让我们一起探索计算机的奥秘&#xff01; 一、ChatGML-6B大模型介绍 ChatGML-6B 是一个大型语言模型,被训练来预测人类语言。它是…

【python】python基础学习笔记

python基础笔记 参考 学习视频 字符串拼接&#xff0c;特殊字符打印 字符串拼接可以用号。print打印最后默认会换行。\为转义符&#xff0c;比如"表示双引号&#xff0c;\n换行 可以自动换行用三个引号 print(see you see you spaceboy someday somewhere)运算 乘方…

人工智能基础部分26-基于知识推理引擎KIE算法的原理介绍与实际应用

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下人工智能基础部分26-基于知识推理引擎KIE算法的原理介绍与实际应用。知识推理引擎(Knowledge Inference Engine, KIE)是一种人工智能技术&#xff0c;其核心原理是基于规则和逻辑的方法来处理复杂的问题。它构建在业…

wayland xmodmap 键盘按键映射失效,转 evremap。wps fcitx5 输入法失效

date: 2024-04-12 Plasma 升级时自动的把 x11 换成了 wayland&#xff0c;导致 xmodmap 的映射失效了 下面确认确实是 wayland $ echo "$XDG_SESSION_TYPE" wayland$ env | grep -E -i x11|xorg|wayland XDG_SESSION_TYPEwayland MEMORY_PRESSURE_WATCH/sys/fs/cg…

华为欧拉系统(openEuler-22.03)安装深信服EasyConnect软件(图文详解)

欧拉镜像下载安装 iso镜像官网下载地址 选择最小化安装&#xff0c;标准模式 换华为镜像源 更换华为镜像站&#xff0c;加速下载&#xff1a; sed -i "s#http://repo.openeuler.org#https://mirrors.huaweicloud.com/openeuler#g" /etc/yum.repos.d/openEuler.r…

MongoDB 初识

1.介绍 什么是Mong MongoDB是一种开源的文档型数据库管理系统&#xff0c;它使用类似于JSON的BSON格式&#xff08;Binary JSON&#xff09;来存储数据。与传统关系型数据库不同&#xff0c;MongoDB不使用表和行的结构&#xff0c;而是采用集合&#xff08;Collection&#x…

美团春招内幕:2024年最全Spring Mobile面试题大全,移动开发秘籍!99%的应聘者都推荐收藏!

在2024年&#xff0c;随着移动互联网的飞速发展&#xff0c;移动优先策略已成为企业发展的重要方向。美团&#xff0c;作为中国领先的电子商务平台之一&#xff0c;特别重视在移动设备上提供卓越的用户体验。为了提升应用的移动友好性&#xff0c;Spring Mobile作为一个专门针对…