1190 反转每对括号间的子串【python3】

文章介绍了两种方法来解决字符串中括号内内容按层反转的问题。第一种是暴力解法,通过记录左括号和右括号的位置,然后反转每对括号内的子串。第二种方法利用栈的数据结构,在遍历字符串过程中动态反转括号内的内容,更高效且节省内存。

题目

给出一个字符串 s(仅含有小写英文字母和括号)。
请你按照从括号内到外的顺序,逐层反转每对匹配括号中的字符串,并返回最终的结果。
注意,您的结果中 不应 包含任何括号。
例如:

输入:s = "(u(love)i)"
输出:"iloveu"
解释:先反转子字符串 "love" ,然后反转整个字符串。

代码&思路

暴力 40ms

初步的设想是找出每一对括号的坐标记录下来,之后对于每一对括号内的子串进行翻转。
如果是先找出(,再找出最近的)的可行性较低,因为对于括号嵌套的情况是比较麻烦的。实际上是要找到最后一个(和它最近的)即配对,然后再找到倒数第二个(以及和它最近的、之前没有配对过的)组成一对。
因此反向思考,先找出第一个)再反向遍历这个右括号前面的部分,找到离它最近的还没有配对过的)。判断左括号是否配对过,我们可以用一个数组记录配对状态。这个方法比先找出(更快一些。

class Solution:
    def reverseParentheses(self, s: str) -> str:
        L=[] # 记录左括号的坐标
        R=[] # 记录相应的右括号位置
        S0=[x for x in s]
        flag=[0]*len(s)
        
        # 记录一对括号的位置:遍历到右括号的时候找到最近的,没有被‘使用’过的左括号
        for i in range(len(s)):
            if s[i]==')':
                R.append(i)
                for j in reversed(range(i)):
                    if flag[j]==0 and s[j]=='(':
                        L.append(j)
                        flag[j]=1
                        break
        #print(R)
        #print(L)
        # 反转每对括号内的子串
        for i in range(len(L)):
            tmp=S0[L[i]+1:R[i]]
            tmp.reverse()
            S0[L[i]+1:R[i]]=tmp 

        ans=''
        for x in S0:
            if x not in '()':
                ans=ans+x
        return ans

栈运用 40ms

有了暴力破解的思路,发现这一题其实可以运用栈来完成,更加简洁。
遍历整个字符串,遍历到除了)以外的字符时,直接入栈。当遍历到)时,出栈,直到把第一个、也就是离它最近的(也给出栈。这个时候已出栈的子串已经是反转后的结果了,左右括号不再入栈,那么就可以保证每次反转的都是一对括号内的子串了。
比较与暴力解的做法,相当于在配对括号的同时就把子串也反转了。
最后运行时间相同,但是内存少了0.1MB

class Solution:
    def reverseParentheses(self, s: str) -> str:
        stack=[] # 栈
        
        for x in s:
            # 不是),入栈
            if x!=')':
                stack.append(x)
            # 遍历到),出栈直到遇见(
            else:
                tmp=[] # 中间栈
                for y in reversed(stack):
                    if y!='(':
                        tmp.append(stack.pop())
                    else: # 遇到(,出栈,出栈后的子串已经是反转的结果,左右括号不再入栈
                        stack.pop()
                        for z in tmp:
                            stack.append(z)
                        break


        return ''.join(stack)

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值