- 有效的括号字符串
给定一个只包含三种字符的字符串:( ,) 和 *,写一个函数来检验这个字符串是否为有效字符串。有效字符串具有如下规则:
任何左括号 ( 必须有相应的右括号 )。
任何右括号 ) 必须有相应的左括号 ( 。
左括号 ( 必须在对应的右括号之前 )。
- 可以被视为单个右括号 ) ,或单个左括号 ( ,或一个空字符串。
一个空字符串也被视为有效字符串。
示例 1:
输入: “()”
输出: True
示例 2:
输入: “(*)”
输出: True
示例 3:
输入: “(*))”
输出: True
注意:
字符串大小将在 [1,100] 范围内。
题解:
因为字符串长度最多为100,所以可以想到是DFS方面,就直接DFS判断,然后减枝避免超时,如何减枝呢?主要是针对’*‘应该改为’(‘还是’)‘还是空,根据括号匹配原则,我们知道如果从左到右依次遍历,出现到左括号数目为sum1,右括号数目为sum2,如果sum2>sum1就直接错误,这个不难理解,然后假设ans1为整个字符串’(‘的数目,ans2为整个字符串’)‘的数目,ans3为整个字符串’*‘的数目,那么有如下关系:
如果’*‘改为’(’,则ans1++,ans3- -;
如果’*‘改为‘)’,则ans2++,ans3- -;
如果’*‘改为空,则ans3- -;
于是判断如果abs(ans1-ans2)>ans3说明错误,为何呢?因为’*'可以看成是调节左右括号数目的存在,如果左右括号数目差异已经大于能够调节的范围,就肯定错误。
AC代码
class Solution {
public:
bool check(string s)
{
int ans=0;
for(int i=0;i<s.length();i++)
{
if(s[i]=='?')continue;
if(s[i]=='(')ans++;
else if(s[i]==')')
{
if(ans==0)return false;
ans--;
}
}
if(ans>0)return false;
return true;
}
string s;
bool dfs(int pos,int ans1,int ans2,int ans3,int sum1,int sum2)
{
if(pos==s.length())
{
if(check(s))
{
return true;
}
return false;
}
if(sum1<sum2)return false;
if(abs(ans1-ans2)>ans3)return false;
bool res=false;
if(s[pos]=='(')
res=dfs(pos+1,ans1,ans2,ans3,sum1+1,sum2);
else if(s[pos]==')')
res=dfs(pos+1,ans1,ans2,ans3,sum1,sum2+1);
else if(s[pos]=='*')
{
s[pos]='(';
res=dfs(pos+1,ans1+1,ans2,ans3-1,sum1+1,sum2);
if(res)return true;
s[pos]=')';
res=dfs(pos+1,ans1,ans2+1,ans3-1,sum1,sum2+1);
if(res)return true;
s[pos]='?';
res=dfs(pos+1,ans1,ans2,ans3-1,sum1,sum2);
if(res)return true;
s[pos]='*';
return false;
}
return res;
}
bool checkValidString(string t) {
s=t;
int ans1=0,ans2=0,ans3=0;
for(int i=0;i<s.length();i++)
if(s[i]=='(')ans1++;
else if(s[i]==')')ans2++;
else if(s[i]=='*')ans3++;
return dfs(0,ans1,ans2,ans3,0,0);
}
};