[Leetcode]678.Valid Parenthesis String
链接:LeetCode678
给定一个只包含三种字符的字符串:( ,) 和\(*\),写一个函数来检验这个字符串是否为有效字符串。有效字符串具有如下规则:
任何左括号 ( 必须有相应的右括号 )。
任何右括号 ) 必须有相应的左括号 ( 。
左括号 ( 必须在对应的右括号之前 )。
\(*\)可以被视为单个右括号 ) ,或单个左括号 ( ,或一个空字符串。
一个空字符串也被视为有效字符串。
示例 1:
输入: "()"
输出: True
示例 2:
输入: "(*)"
输出: True
很明显,我们在遍历字符串的过程中,左,右括号的数量对比对是否是有效字符串是很有帮助的。我们考虑以下问题,假如没有\(*\)号的机制,判定是否有效是十分容易的,我们如何得到个\(*\)号替换后的字符串呢?也就是说,如何判断当前\(*\)应该为"("还是")"?
这里,我们在遍历字符串过程中,设定两个变量lo和hi,分别代表左括号比右括号多的最少个数,和最大个数,那么就有以下结论:
- 当当前字符为左括号(,那么lo和hi都加1;
- 当当前字符为\(*\),那么
- 当lo>0,也就是左括号数量肯定比右括号多了,该\(*\)号通过替换为右括号,显然左括号比右括号多的最少个数需要减1,同时,最大个数加1;
- 否则,最大个数加1即可。
- 当当前字符为右括号),那么
- 当lo>0,则lo需要减1,同时,最大个数也减1
- 否则,最大个数减1 即可(例子:\("*)"\))
- 当出现hi<0:则说明即使将所有*号替换为左括号,也会出现右括号大于左括号的现象,也就是无效的字符串。
最后,判断lo==0即可。
对于这种题,记住代码不如记住思考的方法。首先,我们需要判断每一个\(*\)号是替换左/右括号,还是替换为空,这又与左边的左,右括号有关。那么,我们设置了lo和hi两个变量,实际上也就是这不断探测\(*\)号所处的状态和如何进行状态更换,这里不妨多设几个例子来细细琢磨。
代码如下:
python:
class Solution:
def checkValidString(self, s: str) -> bool:
lo = hi = 0
for ch in s:
if ch=='(':
lo += 1
hi += 1
elif ch == ')':
if lo>0:lo -= 1
hi -= 1
else:
if lo>0:lo -= 1
hi += 1
if hi<0:return False
return lo==0
C++:
class Solution {
public:
bool checkValidString(string s) {
int lo=0,hi=0;
for (char ch:s){
if(ch=='(') {
lo ++;
hi ++;
}
else if(ch==')') {
if(lo>0) lo--;
hi --;
}
else{
if(lo>0) lo--;
hi ++;
}
if(hi<0) return false;
}
return lo==0;
}
};