leetcode -- Remove Invalid Parentheses--又是DFS,BFS的题目
2015-12-25 17:00
513 查看
https://leetcode.com/problems/remove-invalid-parentheses/
valid parentheses definition
字符串中的左右括号数应该相同,而且每个右括号左边一定有其对应的左括号
参考http://bookshadow.com/weblog/2015/11/05/leetcode-remove-invalid-parentheses/改造成自己比较好理解的code style
还是可以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/
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
/article/4901016.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
相关文章推荐
- linux shell 笔记
- 删除Xcode中多余的证书provisioning profile
- 文档的词频-反向文档频率(TF-IDF)计算
- tlb与dll文件区别
- iOS可变数组添加元素 以及可变数组操作
- Cursor的简单使用
- leetcode笔记:Search for a Range
- Android Studio系列教程(三)
- Python @classmethod&@staticmethod 区别
- webstorm快捷键
- MySql按周,按月,按日分组统计数据
- android Settings开发修改定制
- jQuery动画效果
- CircularSeekBar 自定义 圆形 seekbar
- 在线CRM企业:如何在风投潮中屹立?
- 入门训练 序列求和
- js数据过滤
- JAVA输入
- C++学习:const关键字和常量
- iOS项目重构周记(一)