Leetcode 678.有效的括号字符串

Leetcode 678.有效的括号字符串

题目:

给定一个只包含三种字符的字符串:( ,) 和 *,写一个函数来检验这个字符串是否为有效字符串。有效字符串具有如下规则:

1、任何左括号 ( 必须有相应的右括号 )。
2、任何右括号 ) 必须有相应的左括号 ( 。
3、左括号 ( 必须在对应的右括号之前 )。

4、* 可以被视为单个右括号 ) ,或单个左括号 ( ,或一个空字符串。
5、一个空字符串也被视为有效字符串。

示例 1:

​ 输入: “()”
​ 输出: True
示例 2:

​ 输入: “(*)”
​ 输出: True
示例 3:

​ 输入: “(*))”
​ 输出: True
注意: 字符串大小将在 [1,100] 范围内。

首先说一下自己看到这道题的想法,首先想到的是使用两个栈,存放 ‘(’ 的栈和存放 ‘*’ 的栈,遍历字符串对每个字符进行判断,如果是左括号,则入左括号栈,星号则入星号栈,如果是右括号首先判断左括号栈是否为空,不为空首先使用左括号来匹配,否则使用星号来匹配,如果两者都为空,则说明没有与右括号匹配的左括号,返回false;遍历字符串后,存在三种情况:

1、星号栈为空,左括号栈不为空,或则,两种都不为空,但是左括号栈的元素数量大于星号栈元素数量,返回false;

2、左括号栈为空,返回true;

3、两者都不为空,且星号栈元素数量大于等于左括号栈 元素数量,然后根据位置来判断,遍历左括号栈,两个栈每次各弹出一个,对位置进行判断,在此时,星号是作为右括号来匹配左括号的,因此星号的位置必须大于左括号的位置。

刚开始写的时候,脑子抽抽了,没反应过来,使用的栈中存储的是char字符(stack),因此没法判断位置,就换了另一种方法,后来看了解析才反应过来,我可以用栈来存储他们的位置啊(stack)!真是傻逼!!!

第一种方法的代码:

 bool checkValidString(string s)
    {
        stack<int> stStar, stBracket;
        for(int i = 0; i < s.length(); i++)
        {
            if(s[i] == '*')
            {
                stStar.push(i);
            }
            else if(s[i] == '(')
            {
                stBracket.push(i);
            }
            else
            {
                if(!stStar.empty() | !stBracket.empty())
                {
                    stBracket.empty() ? stStar.pop() : stBracket.pop();
                }
                else
                {
                    return false;
                }
            }
        }

        if((stBracket.size() > stStar.size()))
        {
            return false;
        }

        while(!stBracket.empty())
        {
            if(stStar.top() > stBracket.top())
            {
                stStar.pop();
                stBracket.pop();
            }
            else
            {
                return false;
            }
        }

        return true;
    }

然后自己又想了另一种方法,只使用一个栈。这个栈用来存放左括号和星号(stack),也是遍历,遇见左括号和星号都统统压栈,遇见右括号则判断栈顶,如果为星号则弹出并记录弹出的星号的数量,直到遇到左括号,弹出左括号,然后再压入弹出的星号。经过遍历之后,栈中只剩下左括号和星号,因此星号就可以作为右括号来使用了。再遍历这个栈,这次要使用一个int类型的变量count来记录弹出的星号的数量,如果栈顶为左括号则判断count是否大于0,如果大于零,count减一并弹出栈顶元素,否则返回false。如果栈顶为星号则将count加一并将栈顶元素弹出。经过遍历之后只剩两种情况,有栈中有左括号,返回false,否则返回true。
pp
第二种方法代码:

bool checkValidString(string s)
    stack<char> st;
    int count = 0;
    for(int i = 0; i < s.length(); i++)
    {
        if(s[i] == '(' || s[i] == '*')
        {
            st.push(s[i]);
        }
        else
        {
            if(st.empty())
            {
                return false;
            }
            while(!st.empty())
            {
                if(st.top() == '*')
                {
                    count++;
                    st.pop();
                }
                else
                {
                    st.pop();
                    while(count > 0)
                    {
                        st.push('*');
                        count--;
                    }
                    break;
                }
            }

            if(count > 0 )
            {
                count--;
                while(count > 0)
                {
                    st.push('*');
                    count--;
                }
            }
        }
    }

    count = 0;
    while(!st.empty())
    {
        if(st.top() == '(')
        {
            if(count == 0)
            {
                return false;
            }

            st.pop();
            count--;              
        }
        else if(st.top() == '*')
        {
            count++;
            st.pop();
        }
    }

    if(!st.empty())
    {
        if(st.top() == '(')
        {
            return false;
        }
    }
    return true;
}

第三种方法是从题解中看到的,太神奇了!!!自己是真想不到。由于星号可以充当左括号也可以充当右括号,因此可以使用两个变量来记录未匹配的左括号的最大数量(maxlb)以及最小数量(minlb)。

遍历字符串:

1、遇到 ‘(’,maxlb和minlb都需要加一。

2、遇到’)’,需要使用左括号来匹配,因此maxlb和minlb都需要减一,但是如果此时minlb为0,则不需要减一,如果maxlb为0,则说明左括号以及充当左括号的星号不够匹配右括号了,返回false;

3、遇到 ‘*’ ,minlb-- maxlb++。分别是星号充当右括号和左括号的情况。当然如果minlb==0,则minlb不变,此时星号充当空字符串。

遍历结束后,minlb为0则返回true,否则返回false。

第三种方法的代码:

bool checkValidString(string s)
{
    int minlb = 0, maxlb = 0;
    for(int i = 0; i < s.size(); i++)
    {
        switch(s[i])
        {
            case '(' :
                minlb++;
                maxlb++;
                break;
            case '*' :
                minlb > 0 ? --minlb : minlb;
                maxlb++;
                break;
            case ')' :
                minlb > 0 ? --minlb : minlb;
                if(maxlb > 0)
                {
                    maxlb--;
                }
                else
                {
                    return false;
                }
        }
    }

    return minlb == 0;

}

最后,自己的算法基础一般,难免存在错误,希望各位见谅并联系我修正。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值