[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;
    }
};
posted @ 2020-02-06 16:47  Jamest  阅读(266)  评论(0编辑  收藏  举报