题目描述:
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
分享一下在LeetCode上面看到的特别简洁的C代码,感觉很容易理解,
可以利用栈的特性进行解决,
解题思路
① 先判断是否是左括号,是左括号则入栈;
② 不是左括号则先判断栈是否为空为空说明输入的第一个字符就是右括号或者输入的是空字符,非法,返回false;
③ 不是左括号且栈非空,进行匹配,如果匹配不成功直接返回false
④ 不是左括号且栈非空,进行匹配,如果匹配成功则出栈,即栈顶指针减1
⑤ 循环结束(即字符串遍历完毕),检查栈是否空,空则所有左括号匹配完毕
ps: 入栈的时候用左括号相应的右括号入栈而不是直接入栈左括号,这样在匹配的时候直接检查栈顶元素与当前遍历
遍历的字符串是否相等即可完成匹配操作
bool isValid(char* s) {
int len = strlen(s);
//char stack[len + 1]; 这个分配是错误的,原因在下文
char* stack = (char*)malloc(sizeof(char) * (len+1));//表示声明一个字符栈
int top = -1; // 栈顶指针
for (int i = 0; i < len; i++) {
// 遇到左括号时 -- 我们用相应的右括号入栈 -- 方便匹配
if (s[i] == '(') stack[++top] = ')';
else if (s[i] == '[') stack[++top] = ']';
else if (s[i] == '{') stack[++top] = '}';
// 如果不是左括号那就只有右括号了,栈空或不匹配则非法
else if (top == -1 || stack[top] != s[i])
return false;
// 栈非空匹配 -- 出栈 -- 即栈顶指针往下移
else
top--;
}
// 如果遍历完字符串s后栈非空 -- 还有左括号未匹配 -- 非法
// 如果遍历完字符串s后栈为空 -- 所有左括号匹配完 -- 合法
return (top == -1);//返回结果
}
ps:注意数组的长度不可以是变量
C语言里,所有变量空间都是在程序运行之初向系统申请的,包括和指针,它也需要空间,除了一些动态申请方式如malloc函数。没有申请的空间系统是不允许读写的。那么如果一个数组大小是变量定义,则在程序运行前不能确定数组大小,也就无法申请,故不允许。解决的办法如下:
char stack[len+1];
可改为
char* stack = (char*)malloc(sizeof(char) * (len+1));//表示申请一个长度为(len+1)大小的字符数组
这样stack变量就完全可以当作一个数组直接使用了!