有效的括号字符串

文章描述了一个如何使用两个栈(一个用于存储左括号,一个用于存储星号)来检查给定字符串中的括号是否有效的方法。通过遍历字符串,遇到(时入左括号栈,*时入星号栈,遇到)时先检查左括号栈,如果非空则出栈,同时处理星号栈。最后,比较栈顶元素的下标确保它们匹配。
摘要由CSDN通过智能技术生成

只想用一个栈解决,可惜一直解决不了,因为 * 的问题无法解决

看到标答用了两个栈,一个栈存储 (  另一个栈储存 * 

思路:当s[k] 为 ( 或 * 进栈     ,  当s[k] 为 ) 时 , 优先左括号出栈(因为*有可能为空白字符) ,若左括号为空,则*作为(出栈 , 当s[k]为空时,并且左括号的栈也为空,则*作为空白字符,直接返回true  , 当左括号的栈不为空时,则要依次比较栈顶元素的下标,并且此时'('出现的位置一定要在'*'的位置前面(因为此时要匹配成()  )

下面的代码写的比较详细

题目链接:有效的括号字符串

typedef struct Stack

{

    int* arr;

    int rear;

    int size;

}ST;

void STInit(ST* obj)

{

    obj->arr = (int*)malloc(sizeof(int)*105);

    obj->rear = -1;

    obj->size = 0;

}

void STPush(ST* obj,int pos)

{

    if( obj->size == 0 )

    {

        obj->arr[++obj->rear] = pos;

        obj->size++;

        return;

    }

    else

    {

        obj->arr[++obj->rear] = pos;

        obj->size++;

        return ;

    }

}

bool CheckIsEmpty(ST* obj)

{

    return obj->size == 0;

}

void StackPop(ST* obj)

{

    obj->rear--;

    obj->size--;

}

int StackTop(ST* obj)

{

    return obj->arr[obj->rear];

}

bool checkValidString(char* s) {

    ST Left_ST;

    ST Star_ST;

    STInit(&Left_ST);//初始化

    STInit(&Star_ST);

    for( int k = 0 ; s[k] != '\0' ; k++)

    {

        if( s[k] == '('  )

        {

            STPush(&Left_ST,k);//左括号进栈

        }

        else if( s[k] == '*' )

        {

            STPush(&Star_ST,k);//*进栈

        }

        else

        {

            if( !CheckIsEmpty(&Left_ST) )//判断左括号的栈是否为空

            {

                StackPop(&Left_ST);

            }

            else if( !CheckIsEmpty(&Star_ST) )

            {

                StackPop(&Star_ST);

            }

            else return false;

        }

    }

    while( !CheckIsEmpty(&Left_ST) && !CheckIsEmpty(&Star_ST) )

    {

        int pos1 = StackTop(&Left_ST);

        StackPop(&Left_ST);

        int pos2 = StackTop(&Star_ST);

        StackPop(&Star_ST);

        if( pos1 > pos2 )return false;//比较下标

    }

    return CheckIsEmpty(&Left_ST);

}

首先,我们可以将问题转化为求所有非空子串中原语串的个数之和。因为如果一个子串是原语串,那么它的所有子串一定都是原语串。 接着,我们可以使用栈来判断一个子串是否为有效括号字符串(即是否存在将其拆分为 A+B 的方法)。具体地,我们遍历字符串,遇到左括号就将其入栈,遇到右括号就将栈顶元素出栈。如果在出栈前栈为空,或者遍历结束后栈非空,那么当前子串就不是有效括号字符串。 最后,我们可以对所有非空子串进行上述判断,如果是有效括号字符串且没有被划分为 A+B 的形式,那么它就是一个原语串。 时间复杂度为 $O(n^2)$,其中 $n$ 是字符串的长度。具体地,外层循环枚举子串的起点,内层循环枚举子串的终点,判断子串是否为原语串的时间复杂度为 $O(n)$。最坏情况下,字符串中所有字符都是左括号,此时所有子串都是有效括号字符串,因此时间复杂度为 $O(n^2)$。 以下是 Python 代码实现: ```python class Solution: def is_valid(self, s: str) -> bool: stack = [] for c in s: if c == '(': stack.append(c) else: if not stack: return False stack.pop() return not stack def countPrimitives(self, s: str) -> int: n = len(s) count = 0 for i in range(n): for j in range(i, n): if self.is_valid(s[i:j+1]) and not ('(' in s[i:j+1] and ')' in s[i:j+1]): count += 1 return count ``` 可以通过以下代码进行测试: ```python s = Solution() print(s.countPrimitives("(()())(())")) # 输出 2 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值