给定一个只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串 s
,判断字符串是否有效。
有效字符串需满足:
-
左括号必须用相同类型的右括号闭合。
-
左括号必须以正确的顺序闭合。
-
每个右括号都有一个对应的相同类型的左括号。
示例 2:
输入:s = "()[]{}"
输出:true
示例 3:
输入:s = "(]"
输出:false
提示:
1 <= s.length <= 104
s 仅由括号 '()[]{}' 组成
重点来啦!题目解析:
(1)根据观察,出现匹配括号的情况就下面几种:
①括号是成对出现的;例如: 出现左括号'(',下一字符是与之匹配的')' 出现左括号'[',下一字符是与之匹配的']' 出现左括号'{',下一字符是与之匹配的'}' s = "()"; or s = "[]"; or s = "{}" or s = "()[]{}"等等 ②将字符串整体来看,是轴对称的;例如: s = "([{}])"; 显然整个字符串是匹配的 ③除以上两种情况,其余都是不匹配的情况
(2)根据(1)的分析,我们就可以进行编码了;
首先,我们要明确的是,只有出现了左边括号,再出现右边括号才有可能匹配;具体逻辑步骤如下:
①定义一个临时数组:
char temp[20]='\0';
②在遍历数组时若遇到左括号,则将左括号放进数组中,在遇到右括号时,要跟离它最近的左括号进行匹配,只有最近的匹配正确,才能向后;否则就不匹配;下面举个例子:
char s[]="'{','(','[',']','{','}',')','}'"; ①遍历过程中遇到左括号先放到临时数组temp中: temp="'{','(','['"; ②碰到右括号时,在temp中找到最新存入temp的左括号,看是否匹配 ③匹配则temp中的对应左括号出队 temp="'{','('"; ③是不匹配,则证明这个字符串中的括号不是一个有效的括号
举一个反例:
char s[]="'{','(','[',']','{',')','}'"; ①遍历过程中遇到左括号先放到临时数组temp中: temp="'{','(','['"; ②碰到右括号']'时,在temp中找到最新存入temp的左括号,看是否匹配 ③匹配则temp中的对应左括号出队 temp="'{','('"; ③遇到'{'左括号,放入temp数组 temp="'{','(','{'"; ④遇到右括号')',到temp数组中和它最临近的左括号进行匹配 ⑤结果是'{'和')'不匹配,则当前的字符串中的括号群不是一个有效的括号
③当数组s中的第一个元素就是右括号时,当前一定是无效括号
编码思路:
①首先定义一个临时数组temp,用来存放左括号;即,遇到左括号就把该字符写入数组temp
②若第一个字符就是右括号,直接判断当前是无效括号
③循环遍历数组s:
①若遇到的是左括号,将当前的左括号写入数组temp;
②若遇到的是右括号,则在temp数组中找到最新写入数组的左括号;若匹配,则将temp数组该位置上的
值置为空,表示当前的左右括号匹配成功
④遍历结束后,若temp数组为空,即没有需要匹配的左括号,则说明全部括号匹配成功,s数组中的所有括号为有效括号;
代码如下:
bool isValid(char* s) { //s是指向char数组的指针,对所指向的数组进行遍历
//①定义临时数组temp
char temp[100000]="\0";
int i,j=0;
//②若数组s中的第一个字符就是右括号,则直接判断为无效括号,返回false
if( (s[0]=='}') || (s[0]==')') || (s[0]==']') )
{
return false;
}
//③遍历s中的字符,进行括号的有效性匹配
for(i=0;i<strlen(s);i++)
{
//④当字符为左括号时,放入临时数组temp,等待匹配
if( (s[i]=='{') || (s[i]=='(') || (s[i]=='[') )
{
temp[j]=s[i];
j++;
}
if( (s[i]=='}') || (s[i]==')') || (s[i]==']') )
{
//⑤这里的j--是因为:左括号写入temp后会j++,所以j是刚写入的左括号的后一位,j--使j回到有效位
j--;
//⑥为右括号,则需要到存储左括号的temp数组里匹配
switch(s[i])
{
case '}':
if(temp[j]=='{'){
temp[j]='\0';
// j--;
}else{
return false;
}
break;
case ')':
if(temp[j]=='('){
temp[j]='\0';
// j--;
}else{
return false;
}
break;
case ']':
if(temp[j]=='['){
temp[j]='\0';
// j--;
}else{
return false;
}
break;
}
}
continue;
}
//最后若所有的左括号都匹配完了,则说明是有效括号
if(temp[0]!='\0'){
return false;
}
return true;
}
上面的代码似乎是没有问题的,但是!有一种情况没有考虑到 假如数组s为:s="(){}}{";前两对(){}是匹配成功的,但是到了'}'时,此时数组数组temp中的两个左括号都匹配完毕,数组temp为空,在执行循环时,j--;就会出现数组temp的越界问题,如图:
怎么避免上面的问题呢?
我们在j--之前先判断temp数组是否为空,若为空,则证明当前的右括号无匹配对象了,为无效括号,返回false即可!
if(j>0)
{
j--;
}else{
return false;
}
正确编码~
bool isValid(char* s) { //s是指向char数组的指针,对所指向的数组进行遍历
//①定义临时数组temp
char temp[100000]="\0";
//②若数组s中的第一个字符就是右括号,则直接判断为无效括号,返回false
if( (s[0]=='}') || (s[0]==')') || (s[0]==']') )
{
return false;
}
//③遍历s中的字符,进行括号的有效性匹配
int i,j=0;
for(i=0;i<strlen(s);i++)
{
//当字符为左括号时,放入临时数组
if( (s[i]=='{') || (s[i]=='(') || (s[i]=='[') )
{
temp[j]=s[i];
j++;
}
if( (s[i]=='}') || (s[i]==')') || (s[i]==']') )
{
if(j>0)
{
j--;
}
else{
return false;
}
//若为有括号,则需要到左括号里进行匹配
switch(s[i])
{
case '}':
if(temp[j]=='{'){
temp[j]='\0';
// j--;
}else{
return false;
}
break;
case ')':
if(temp[j]=='('){
temp[j]='\0';
// j--;
}else{
return false;
}
break;
case ']':
if(temp[j]=='['){
temp[j]='\0';
// j--;
}else{
return false;
}
break;
}
}
continue;
}
if(temp[0]!='\0'){
return false;
}
return true;
}
以上内容是根据题目一步一步分析,遵守算法规则编码的,但是存在代码不精简的问题,会出一个精简版的代码哦~出现的问题都是我在提交代码过程中测试用例不通过总结出来的,请各位友友在注意~