leetcode -- Remove Invalid Parentheses--又是DFS,BFS的题目

https://leetcode.com/problems/remove-invalid-parentheses/

valid parentheses definition

字符串中的左右括号数应该相同,而且每个右括号左边一定有其对应的左括号

思路1 DFS

这里其实就是试着去remove其中一个左括号或者右括号,对于剩下的字符串,继续看remove哪一个左括号或者右括号,知道remove以及不能降低invalid parentheses了(这个剪枝条件)。这就是DFS

参考http://bookshadow.com/weblog/2015/11/05/leetcode-remove-invalid-parentheses/改造成自己比较好理解的code style

class Solution(object):
    def removeInvalidParentheses(self, s):
        """
        :type s: str
        :rtype: List[str]
        """
        def dfs(s, res):
            mi = calc(s)
            if mi == 0:
                res.append(s[:])
                return
            ans = []
            for x in range(len(s)):
                if s[x] == '(' or s[x] == ')':
                    ns = s[:x] + s[x+1:]
                    if ns not in visited and calc(ns) < mi:
                    #这里一定要有一个visited 来记录,因为对于((()来说,去掉第一个左括号跟去掉第二个左括号,剩下的string是一样的,不需要重复的取dfs
                        visited.add(ns)
                        dfs(ns, res)

        def calc(s):#计算有多少invalid的括号,这里可以用下面BFS的计算invalid括号的程序
            a = b = 0
            for c in s:
                a += {'(' : 1, ')' : -1}.get(c, 0)
                b += a < 0
                a = max(a, 0)
            return a + b

        visited = set([s])
        res = []
        dfs(s,res)
        return res

自己重写的code, DFS

class Solution(object):
    def removeInvalidParentheses(self, s):
        """
        :type s: str
        :rtype: List[str]
        """
        def dfs(s, visited):
            m = calc(s)
            if m == 0:
                res.append(s)
            else:
                for i in xrange(len(s)):
                    if s[i] in '()':
                        new_s = s[:i] + s[i+1:]
                        if new_s not in visited and calc(new_s) < m:
                            visited.append(new_s)
                            dfs(new_s, visited)
        def calc(s):
            a, b = 0, 0
            for x in s:
                #这里a相当于从左到右加上所有的所右括号,如果其大于或者等于0,那么肯定没有invalid括号
                #如果a等于0,那么肯定没有invalid
                #如果a大于0,例如'()(',这里a就记录了多出来的左括号个数
                #如果a小于0,例如‘))(’,这里a首先是负数,然后让b来记录负数,负数为invalid右括号个数。
                #所以这里a应该是记录invalid左括号个数,b记录invalid右括号个数
                a += {'(':1, ')':-1}.get(x,0)
                b += a < 0
                a = max(a, 0)
            return a + b

        res = []
        dfs(s, [])
        return res

思路2 BFS

http://www.cnblogs.com/grandyang/p/4944875.html

还是可以remove original 字符串的每一个 左括号或者右括号去做试探,但是这里是BFS,例如,就是remove第一个左括号之后,下一步不是递归地处理剩下的字符串,而是处理原来的original字符串remove第二个左括号或者右括号之后的字符串。直到已经在original字符串上,穷尽了所有可能remove掉一个左括号或者右括号的情况,再继续对队列里的字符串继续穷举remove。。。。

这里就是每一层逐个scan,对于一个字符串,子节点就是对每个位置移除左括号或者右括号剩下的字符串。因为题目要求求出remove最少数目的括号已达到valid,那么就是说只要在scan某一层的时候,如果出现valid的括号字符串,那么就不应该继续下一层的搜索了。所以这里引入了一个found变量在这里。

但是这里有一点没有理解的就是,根据下图,如果q = [1,2,3],这里数字表示node,那么1 pop出来之后,如果invalid,则加入4,5,q变成[2,3,4,5], 然后2 pop出来之后,如果invalid,则加入6,7,q变成[3,4,5,6,7],然后3pop出来之后,如果valid,found变成了True,但是q还是[4,5,6,7],q里面的元素已经不是最少移除invalid括号了,如果这些节点有valid的话,还是有可能被加入到最后的结果中。那么就不符合题意了?why?但是oj还是通过了。
这里写图片描述

参考:http://www.hrwhisper.me/leetcode-remove-invalid-parentheses/

class Solution(object):
    def removeInvalidParentheses(self, s):
        """
        :type s: str
        :rtype: List[str]
        """
        if not s: return ['']
        q, ans, vis = [s], [], set([s])
        found = False
        while q:
            cur = q.pop(0)
            if self.isValidParentheses(cur):
                found = True#只要found变量变成True,说明在这一层已经能够移除最少的invalid括号达到剩下字符串是valid的目的了,所以不需要继续往下一层搜索,已经被加入到q中的子节点
                ans.append(cur)
            elif not found:
                for i in xrange(len(cur)):
                    if cur[i] == '(' or cur[i] == ')':
                        t = cur[:i] + cur[i + 1:]
                        if t not in vis:
                            q.append(t)
                            vis.add(t)
        return ans

    def isValidParentheses(self, s):#很好理解,多看看
        cnt = 0
        for c in s:
            if c == '(':
                cnt += 1
            elif c == ')':
                if cnt == 0: return False
                cnt -= 1
        return cnt == 0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值