【题目描述】
给定一个只包括'(',')','[',']','{','}' 的字符串 s
,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
【测试用例】
示例1:
输入:s = "()"
输出:true
示例2:
输入:s = "()[]{}"
输出:true
示例3:
输入:s = "(]"
输出:false
【思路分析】
可能以前见过这个题目,我看到题目的第一时间想到的方法就是栈。
联想数学算式,比如{1×[2×(3-1)+1]-1},要先计算小括号,再计算中括号,最后计算大括号,那么就得先找到小括号的左括号,再找到小括号的右括号,计算出括起来的算式的结果;再找中括号的左括号,中括号的右括号....
换种理解方式,就是要完成括号配对的过程。当遇见一个左括号时(不论大/中/小括号的左括号),那么下一个括号只能有两种情况:
1.与该左括号相配对的右括号。此时可以直接删去配对成功的这两个括号,开始配对前一个左括号。
2.另一个新的左括号。此时这个新的左括号作为下一轮的待匹配括号。
不满足上述两种情况的均为匹配失败,直接返回false。
例如,遇见左括号1:{ 时,下一个匹配的只能是 '}' 或者新的左括号。上例中,下一个匹配到新的左括号2:( ,则2号更新为待匹配括号,那么下一个括号只能是与2号配对的 ')' 或者新的左括号。下一个括号3与括号2配对成功,直接删去括号2、3,开始配对前一个左括号,也就是括号1。括号1的下一个括号4是个左括号,更新为待匹配括号,需要 ']' 或者新的左括号;继续往后5号是新的左括号,更新为待匹配括号,需要 ')' 或者新的左括号;下一个括号6与括号5配对成功,删去,开始配对左括号4;下一个括号7与括号4匹配,删去,开始配对左括号1;下一个括号8与括号1匹配,删去。当遍历到最后一个括号,且前面的所有括号都被删去之后,说明配对成功,返回true。
上述过程实际上非常符合栈的特点:后进先出。后入栈的左括号要先被匹配。具体实现方式:遇见左括号直接入栈,遇见右括号则取出栈顶的左括号,如配对成功,遍历下一个括号,如配对失败,直接返回false。当所有括号都遍历完后,如果栈为空,则表示所有括号都匹配成功,返回true。
【参考代码】
C实现
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
//easy-20-有效的括号
bool isValid(char* s);
char match(char c);
int main(){
char s[100];
scanf("%s",s);
bool res = isValid(s);
if(res){
printf("true");
}else{
printf("false");
}
return 0;
}
bool isValid(char* s) {
int top=0,i;
char stack[strlen(s)];
for(i=0;i<strlen(s);++i){
if(s[i]=='(' || s[i]=='[' || s[i]=='{'){
stack[top++]=s[i];
continue;
}
char ch = match(s[i]);
if(top==0 || (ch!=stack[top-1])){
return false;
}else{
top--;
}
}
return top==0;
}
char match(char c){
if(c==')'){
return '(';
}else if(c==']'){
return '[';
}else if(c=='}'){
return '{';
}
}
C++实现
在C中,使用一个函数match来实现括号的对应。而在C++中,使用容器unordered_map来实现,可以提高代码的可扩展性。另一方面,C++的STL中有现成的函数,更加简化。
#include <iostream>
#include <unordered_map>
#include <stack>
#include <string>
using namespace std;
//easy-20-有效的括号
class Solution {
public:
bool isValid(string s);
};
bool Solution::isValid(string s){
int i;
unordered_map<char, char> match={
{')','('},
{']','['},
{'}','{'}
};
stack<char> stack;
for(i=0;i<s.size();++i){
if(s[i]=='(' || s[i]=='[' || s[i]=='{'){
stack.push(s[i]);
continue;
}
char ch = match[s[i]];
if(stack.empty() || (ch!=stack.top())){
return false;
}else{
stack.pop();
}
}
return stack.empty();
}
int main(){
Solution sol;
string s;
cin>>s;
bool res = sol.isValid(s);
if(res){
cout<<"true"<<endl;
}else{
cout<<"false"<<endl;
}
return 0;
}