【LeetCode 30天挑战活动】Day 16. Valid Parenthesis String

阴间作业和阴间小学期害人不浅: (题目描述(我太懒了就直接复制原题了)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 s...
摘要由CSDN通过智能技术生成

阴间作业和阴间小学期害人不浅: (

题目描述

(我太懒了就直接复制原题了)

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 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值