L11.【LeetCode笔记】有效的括号
目录
1.题目
2.分析
理解题意
解决方法
草稿代码
编辑
逐一排错
1.当字符串为"["时,分析代码
2.当字符串为"()]"时,分析代码
正确代码(isValid函数部分)
提交结果
3.代码优化
1.题目
https://leetcode.cn/problems/valid-parentheses/description/
给定一个只包括
'('
,')'
,'{'
,'}'
,'['
,']'
的字符串s
,判断字符串是否有效。有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
示例 1:
输入:s = "()"
输出:true
示例 2:
输入:s = "()[]{}"
输出:true
示例 3:
输入:s = "(]"
输出:false
示例 4:
输入:s = "([])"
输出:true
提示:
1 <= s.length <= 104
s
仅由括号'()[]{}'
组成
2.分析
理解题意
括号能匹配应该是成对出现(像(]不为成对出现),分为两种情况:
不嵌套:()[]{}
嵌套:([])
解决方法
1.出现左括号,就将其入栈
2.出现右括号,就将其对应的左括号出栈
例如:([{}])
入栈图
有关于栈的操作函数参见97.【C语言】数据结构之栈, 但也不能完全挪用
头文件的int要改为char
typedef int STDataType;
步骤:初始化栈-->操作栈(push&pop)-->销毁栈
出栈时先取括号,再出栈,接着判断括号是否匹配.若匹配,则继续进行;若不匹配,则返回false
但if语句判断匹配的情况没有任何作用
if (*s==')'&& top=='(')
{
}
应该去判断不匹配的情况
if (*s==')'&& top !='(')
草稿代码
typedef char STDataType;
typedef struct Stack
{
STDataType* a;
int top;
int capacity;
}ST;
void STInit(ST* ps)
{
assert(ps);
ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);
if (ps->a == NULL)
{
perror("malloc");
return;
}
ps->capacity = 4;
ps->top = 0;//top栈顶元素的下一个位置
}
void STDestory(ST* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->top = 0;
ps->capacity = 0;
}
void STPush(ST* ps, STDataType x)
{
assert(ps);
if (ps->top == ps->capacity)
{
STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * ps->capacity * 2);
if (tmp == NULL)
{
perror("realloc");
return;
}
ps->a = tmp;
ps->capacity *= 2;
}
ps->a[ps->top] = x;
ps->top++;
}
bool STEmpty(ST* ps)
{
assert(ps);
return ps->top == 0;
}
void STPop(ST* ps)
{
assert(ps);
assert(!STEmpty(ps));//确保不越界
ps->top--;
}
STDataType STTop(ST* ps)//访问栈顶元素
{
assert(ps);
assert(!STEmpty(ps));//确保不越界
return ps->a[ps->top - 1];
}
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++;
}
STDestory(&st);
return true;
}
看起来提供的测试用例的执行结果没有问题
但是当出现类似"["、"()]"等的情况时,会出错
逐一排错
1.当字符串为"["时,分析代码
进入while循环后,[入栈,s++,下一次*s==\0,结束循环,STDestory(&st);后返回true
栈不为空(有[)应该返回false,所以在循环结束后,应该用一个变量接收STEmpty的返回值
while循环后的几行改为:
bool ret=STEmpty(&st);
STDestory(&st);
return ret;
但这样仍然过不了"()]"测试用例
2.当字符串为"()]"时,分析代码
断言生效STTop: Assertion `!STEmpty(ps)' failed
(入栈-->)出栈-->*s==']'时,while循环的STPush(&st,*s);不执行,当执行else的第一个语句char top=STTop(&st);时,assert(!STEmpty(ps));生效
即当栈为空时,访问栈顶元素是错误的!
在else中,先判断栈是否为空,若为空,则返回false即可
正确代码(isValid函数部分)
bool isValid(char* s)
{
ST st;
STInit(&st);
while(*s)
{
if (*s=='('||*s=='['||*s=='{')
{
STPush(&st,*s);
}
else
{
if (STEmpty(&st))
return false;
char top=STTop(&st);//注意
STPop(&st);
if ((*s==')'&&top !='(')
||(*s==']'&&top !='[')
||(*s=='}'&&top !='{'))
return false;
}
s++;
}
bool ret=STEmpty(&st);
STDestory(&st);
return ret;
}
提交结果
3.代码优化
返回前应该销毁栈,防止内存泄漏
bool isValid(char* s)
{
ST st;
STInit(&st);
while(*s)
{
if (*s=='('||*s=='['||*s=='{')
{
STPush(&st,*s);
}
else
{
if (STEmpty(&st))
{
STDestory(&st);//修改后
return false;
}
char top=STTop(&st);
STPop(&st);
if ((*s==')'&&top !='(')
||(*s==']'&&top !='[')
||(*s=='}'&&top !='{'))
{
STDestory(&st);//修改后
return false;
}
}
s++;
}
bool ret=STEmpty(&st);
STDestory(&st);
return ret;
}