题目
给定一个只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串 s
,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
想法
最初没有想到用栈来解决这一茬,所以设计的代码如下,代码的主要思想为遇到左括号使用字符串函数strstr()来匹配右括号,如果找不到就直接返回false,能找到将右括号对应位置改为'0',如果遍历过程中遇到'0'则跳过,若遇到未被转化为'0'的右括号说明其不是成对的,所以返回false。遍历完成后则返回true。
bool isValid(char* s) {
for(int i=0;i<strlen(s);i++){
if(s[i]=='0'){
continue;
}
if(s[i]==')'||s[i]=='}'||s[i]==']'){
return false;
}
if(s[i]=='('){
char* p=strstr(s,")");
if(p==NULL){
return false;
}
else{
*p='0';
}
}
if(s[i]=='{'){
char* p=strstr(s,"}");
if(p==NULL){
return false;
}
else{
*p='0';
}
}
if(s[i]=='['){
char* p=strstr(s,"]");
if(p==NULL){
return false;
}
else{
*p='0';
}
}
}
return true;
}
但是最后运行并未成功,当遇到(【)】这种情况时仍然返回true,发生了判断错误。因为】应该出现在)之前和【形成一个闭合才是正确的。
正确解法
官方使用的是栈的思想来解决的。代码如下:
char judge(char a){
if (a == '}') return '{';
if (a == ']') return '[';
if (a == ')') return '(';
return 0;
}
bool isValid(char* s){
int n = strlen(s);
if(n % 2 == 1){
return false;
}
int str[n];
int top = 0;
for(int i = 0;i < n;i++){
char x = judge(s[i]);
if(x){
if(top == 0 || str[top - 1] != x){
return false;
}
top--;
}
else{
str[top++]=s[i];
}
}
if(top == 0){
return true;
}
else{
return false;
}
}
其主要思想是先判断字符串长度,如果是奇数那么至少是不满足括号成对这一条件的。接下来创建一个新的字符数组str和头指针top。接下来对原字符串遍历,遇到左括号将其存储在str数组中,top执行++操作。如果遇到右括号,则对其经行judge判段,得到相对应的有效左括号。如果此时top=0,说明第一个括号就是右括号,格式错误返回false;如果此时右括号的前一个位置所对应的字符不是他所匹配的左括号,也格式错误返回false;如果都不满足则执行top--,相当于将此次匹配的左右括号移除数组(栈)。当循环完毕后还未返回false,则对top进行判断,如果top==0,则说明都匹配完成,返回true;如果top!=0,则说明可能存在类似'(('这种情况,返回false。