您的位置:首页 > 其它

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

2015-12-25 17:00 513 查看
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

/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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: