阴间作业和阴间小学期害人不浅: (
题目描述
(我太懒了就直接复制原题了)
Given a string containing only three types of characters: ‘(’, ‘)’ and ‘*’, write a function to check whether this string is valid. We define the validity of a string by these rules:
Any left parenthesis ‘(’ must have a corresponding right parenthesis ‘)’.
Any right parenthesis ‘)’ must have a corresponding left parenthesis ‘(’.
Left parenthesis ‘(’ must go before the corresponding right parenthesis ‘)’.
‘*’ could be treated as a single right parenthesis ‘)’ or a single left parenthesis ‘(’ or an empty string.
An empty string is also valid.
题目中主要是要理解*
可以有三种匹配方式
(1)作为左括号匹配
(2)作为右括号匹配
(3)忽略不计(实际左括号和右括号可以完美匹配的时候就不需要*
了)
解题思路
法一: 一看到括号匹配,第一反应是用栈来完成。而这题当中多了一个*
的处理,由于无法在遇到*
的时候是无法确定它到底是哪种匹配方式,于是我就想用一个额外的数据结构将*
存下来,在遇到右括号去进行匹配的时候,和最后还剩左括号需要右括号来匹配的时候,就refer to这个*
看能不能匹配上。
在第一次写的时候,我用了一个int
变量来存放*
的数量,当发现实际左右括号匹配不上的时候就看是否有*
来做一个通配。但很快发现这个方法是有问题的。
以"**("
为例,遍历下来会得到*
的数量为2,最后发现左括号的时候refer to*
的数量发现有*
可以匹配,那么结果就为true
,但很显然这个字符串是不符合要求的。
在上面的方法中,我忽略了一个关键问题,就是*
和(
的相对位置,很显然,在(
之前出现的*
是无法作为)
来匹配的。因此,我在保存下无法确定的*
时,不能只记录下数量,而是要将相对位置也记录下来。于是改进思路,用两个栈来存放,一个作为主栈,存放(
和*
并保持相对位置,另一个作为辅助栈,在遇到)
要先去主栈中找(
时临时存放*
。大致步骤如下(栈1为主栈,栈2为辅助栈):
遍历字符串的每个字符,
(1)遇到(
或*
,入栈1
(2)遇到)
,从栈顶开始在主栈中找(
,如果遇到的是*
,就将其入栈2,直至找到(
;如果最后栈1空,就用*
来匹配
(3)匹配完)
后将栈2中的*
还原至栈1中
最后判断是否匹配成功:
在栈1中找(
,并将一路上遇到的*
入栈2,如果遇到的(
都能有*
匹配,且最后栈1空,则匹配成功,否则失败
这个方法时间复杂度O(N²),空间复杂度O(N)
代码如下:
class Solution {
public boolean checkValidString(String s) {
if (s == null || s.length() == 0) {
return true;
}
Stack<Character> mainStack