题目描述
题意解读
说白了这道题就是 内部会输入一个字符串,字符串里面有若干字符,每个字符只可能是( { [ ) } ]
这六个括号中的一个,你需要做的是 写一段代码来判断给定的字符串中的这些括号是否匹配,什么叫括号是否匹配?
首先有左括号就得有对应的右括号,必如说 " ( [ " 这就不是有效的括号
再者左括号和对应的右括号位置要对应,比如说: " ( [ ) ] " 这就不是有效的括号
思路
遍历字符串的每个字符
如果是左括号就入栈,如果是右括号就让左括号出栈和右括号进行匹配,看是否匹配
代码实现
按照上述思路:我们先初步实现一下
下面要用到栈,因此我们把前面博客写过的栈的实现代码直接搬过来
#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
#include<assert.h>
typedef char STDataType;
typedef struct Stack
{
STDataType* a;
int top;
int capacity;
}ST;
//栈初始化
void STInit(ST* pst);
//栈的销毁
void STDestroy(ST* pst);
//压栈
void STPush(ST* pst,STDataType x);
//出栈
void STPop(ST* pst);
//获取栈顶元素
STDataType STTop(ST* pst);
//判空
bool STEmpty(ST* pst);
//获取size
int STSize(ST* pst);
//栈的初始化
void STInit(ST* pst)
{
assert(pst);
pst->a = NULL;
//pst->top = -1; //top指向栈顶元素
pst->top = 0; //top指向栈顶元素的下一个位置
pst->capacity = 0;
}
//栈的销毁
void STDestroy(ST* pst)
{
assert(pst);
free(pst->a);
pst->a = NULL;
pst->top = pst->capacity = 0;
}
//压栈
void STPush(ST* pst, STDataType x)
{
if (pst->top == pst->capacity)
{
int newCapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
STDataType* tmp = realloc(pst->a, newCapacity * sizeof(STDataType));
if (tmp == NULL)
{
perror("realloc fail\n");
return;
}
pst->a = tmp;
pst->capacity = newCapacity;
}
pst->a[pst->top] = x;
pst->top++;
}
//出栈
void STPop(ST* pst)
{
assert(pst);
assert(!STEmpty(pst));
pst->top--;
}
//获取栈顶元素
STDataType STTop(ST* pst)
{
assert(pst);
assert(!STEmpty(pst));
return pst->a[pst->top - 1];
}
//判空
bool STEmpty(ST* pst)
{
return pst->top == 0;
//或者写成
// return !(pst->top)
}
//获取栈的元素个数
int STSize(ST* pst)
{
assert(pst);
return pst->top;
}
下面是这道题的主体代码
bool isValid(char * s){
ST st;
STInit(&st);
while(*s)
{
if(*s == '(' || *s == '[' || *s == '{')
{
STPush(&st, *s);
}
else
{
char top = STTop(&st);
STPop(&st);
if(*s == ']' && top!='['
|| *s == '}' && top != '{'
|| *s == ')' && top != '(')
{
return false;
}
}
s++;
}
return True;
}
下面详细解释一下这段代码的要点:
②s是题目中已经给定的函数形参,是一个字符串,字符串是以'\0'为结束标志的,因此while(*s)就作为while循环体继续执行的条件
③If else 用来判断是左括号还是右括号,左括号就入栈,右括号就与出栈的左括号进行比较
④这部分是关键,意思就是只要有一对括号没匹配上,那么就直接返回false
遇到的问题
问题一
就这样直接运行代码,发现并没有通过测试,分析题目所给未通过示例,可以发现,当给定字符串只有左括号时,会出现问题
因为只有左括号的时候,else分支压根没有进去,当遍历完字符串时,直接来到最后一句return true了,因此出现了问题
怎么改正呢?我们不妨思考一下,当题中所给字符串是有效的括号时,按照我们的方法,栈最后一定是空的,因此我们可以在最后加上这么一段代码:
判断一下栈是否为空,如果为空,则返回True,不为空,返回False,符合我们分析的结果
问题二
但是直接提交仍然有问题
可以看到当字符串只有右括号的时候,直接进入else语句中的STTop代码,但是由于没有左括号入栈,因此栈为空,STTop中的assert断言就会报错
改进:只需要在else语句中加入if条件判断,如果为空,直接返回false即可
更严谨的写法~
不过我们学编程还是要更加严谨一点~,该题中的栈ST是我们自己创建的,那么最后当然应该销毁了,虽然Leetcode并没有进行这方面严格检查,但是养成好习惯还是很重要的~
完整代码
#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
#include<assert.h>
typedef char STDataType;
typedef struct Stack
{
STDataType* a;
int top;
int capacity;
}ST;
//栈初始化
void STInit(ST* pst);
//栈的销毁
void STDestroy(ST* pst);
//压栈
void STPush(ST* pst,STDataType x);
//出栈
void STPop(ST* pst);
//获取栈顶元素
STDataType STTop(ST* pst);
//判空
bool STEmpty(ST* pst);
//获取size
int STSize(ST* pst);
//栈的初始化
void STInit(ST* pst)
{
assert(pst);
pst->a = NULL;
//pst->top = -1; //top指向栈顶元素
pst->top = 0; //top指向栈顶元素的下一个位置
pst->capacity = 0;
}
//栈的销毁
void STDestroy(ST* pst)
{
assert(pst);
free(pst->a);
pst->a = NULL;
pst->top = pst->capacity = 0;
}
//压栈
void STPush(ST* pst, STDataType x)
{
if (pst->top == pst->capacity)
{
int newCapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
STDataType* tmp = realloc(pst->a, newCapacity * sizeof(STDataType));
if (tmp == NULL)
{
perror("realloc fail\n");
return;
}
pst->a = tmp;
pst->capacity = newCapacity;
}
pst->a[pst->top] = x;
pst->top++;
}
//出栈
void STPop(ST* pst)
{
assert(pst);
assert(!STEmpty(pst));
pst->top--;
}
//获取栈顶元素
STDataType STTop(ST* pst)
{
assert(pst);
assert(!STEmpty(pst));
return pst->a[pst->top - 1];
}
//判空
bool STEmpty(ST* pst)
{
return pst->top == 0;
//或者写成
// return !(pst->top)
}
int STSize(ST* pst)
{
assert(pst);
return pst->top;
}
bool isValid(char * s){
ST st;
STInit(&st);
while(*s)
{
if(*s == '(' || *s == '[' || *s == '{')
{
STPush(&st, *s);
}
else
{
if(STEmpty(&st))
{
STDestroy(&st);
return false;
}
char top = STTop(&st);
STPop(&st);
if(*s == ']' && top!='['
|| *s == '}' && top != '{'
|| *s == ')' && top != '(')
{
STDestroy(&st);
return false;
}
}
s++;
}
bool ret = STEmpty(&st);
STDestroy(&st);
return ret;
}
本篇有效的括号这道题就分享到这啦,欢迎大家交流指正~