def paren(n):
lst = ['(' for x in range(n)]
current_string = ''.join(lst)
solutions = list()
for i in range(len(current_string)+1):
close(current_string, n, i, solutions)
return solutions
def close(current_string, num_close_parens, index, solutions):
"""close parentheses recursively"""
if num_close_parens == 0:
if current_string not in solutions:
solutions.append(current_string)
return
new_str = current_string[:index] + ')' + current_string[index:]
if num_close_parens and is_valid(new_str[:index+1]):
return close(new_str, num_close_parens-1, index+1, solutions)
else:
return close(current_string, num_close_parens, index+1, solutions)
def is_valid(part):
"""True if number of open parens >= number of close parens in given part"""
count_open = 0
count_close = 0
for paren in part:
if paren == '(':
count_open += 1
else:
count_close += 1
if count_open >= count_close:
return True
else:
return False
print paren(3)
以上代码是我尝试解决上述问题。它为n<3
提供了足够的解决方案,但除此之外,它没有给出所有解决方案。例如,当n=3
时,它会输出['()()()', '(())()', '((()))']
而忽略'()(())'
。如何修改代码以正确输出所有可能的解决方案?
答案 0 :(得分:7)
这是一个递归生成器,可以生成所有有效的解决方案。与其他答案不同,此答案从不计算需要过滤的重复或无效字符串。这与this answer to a previous question中的算法几乎相同,但它不需要非递归的辅助函数:
def paren(left, right=None):
if right is None:
right = left # allows calls with one argument
if left == right == 0: # base case
yield ""
else:
if left > 0:
for p in paren(left-1, right): # first recursion
yield "("+p
if right > left:
for p in paren(left, right-1): # second recursion
yield ")"+p
答案 1 :(得分:6)
如果不必使用递归,这似乎有效:
from itertools import permutations
def valid(test):
open, close = 0, 0
for c in test:
if c == '(':
open += 1
elif c == ')':
close += 1
if close > open:
return False
return True
def paren(n):
perms = set(''.join(p) for p in permutations('(' * n + ')' * n))
return [s for s in perms if valid(s)]
答案 2 :(得分:1)
使用递归和多效率高于itertools.permutations
:
def paren(n):
ps = set(['(' * n + ')' * n])
for i in range(1, n):
for a in paren(i):
for b in paren(n-i):
ps.add(a + b)
return ps
由于重复递归,使用functools.lru_cache
也可以提高效率。
或者,通过内置的memoization,
def paren(n, known={}):
if n in known:
return known[n]
ps = set(['(' * n + ')' * n])
for i in range(1, n):
for f in paren(i, known):
for s in paren(n-i, known):
ps.add(f + s)
known[n] = ps
return ps
答案 3 :(得分:1)
我是动态编程和递归的新手,但这是我没有递归的解决方案。请告诉我为什么它不起作用或者这是否是可接受的解决方案:
class Parenthesis(object):
def __init__(self, parens):
self.parens = parens
self.my_valid_parens = {
1: ['()'],
2: ['()()', '(())']
}
def generate_valid_paren(self):
if self.parens <= 2:
return self.my_valid_parens[self.parens]
i = 3
while i <= self.parens:
new_set = []
for each in self.my_valid_parens[i-1]:
new_set += set([each + '()', '()' + each, '(' + each + ')'])
self.my_valid_parens[i] = list(new_set)
i += 1
if __name__ == '__main__':
num = 4
p = Parenthesis(num)
p.generate_valid_paren()
print p.my_valid_parens[num]
以下是分别为num = 3和4时的输出:
3: ['(()())', '()()()', '()(())', '(())()', '((()))']
4: ['(()())()', '()(()())', '((()()))', '()()()()', '(()()())', '()()(())', '(()(()))', '()(())()', '((())())', '(())()()', '()(())()', '()((()))', '(((())))', '((()))()']
答案 4 :(得分:0)
似乎任务归结为生成具有N + 1个节点的所有可能树。让我们假设在整个字符串周围有另一对parens,然后对于N = 3,所有可能的树将是
o | o ((())) | o | o o / \ (())() o o | o o / \ o o ()(()) | o o ()()() /|\ o o o
我现在无法为您提供任何代码(因此CW),但请参阅this paper - 它似乎完全处理了这个问题。
答案 5 :(得分:0)
对于N == 3,有5种有效组合:()()(),((())),(()()),(())()和()(())。
递归算法的工作原理如下:
这是Java代码:
public static ArrayList<String> parentheses(int n, int left, int right) {
ArrayList<String> results = new ArrayList<String>();
if (left == n && right == n) {
results.add("");
}
if (left < n) {
ArrayList<String> subResults = parentheses(n, left + 1, right);
for (String subResult : subResults) {
String newResult = "(" + subResult;
results.add(newResult);
}
}
if (left > right) {
ArrayList<String> oldResults = parentheses(n, left, right + 1);
for (String oldResult : oldResults) {
String newResult = ")" + oldResult;
results.add(newResult);
}
}
return results;
}
最后,使用:
调用递归函数parentheses(n, 0, 0);
答案 6 :(得分:0)
这是我的解决方案
from itertools import permutations
n = 3
input = ("( " * n) + (") " * n)
in_list = [f for f in input.split(" ") if f]
possible_combinations = list(permutations(in_list, n*2))
valid_list = []
def ret_valid(el):
num_open = num_close = 0
for val in el:
if val == "(":
num_open += 1
else:
num_close += 1
if num_close > num_open:
return False
return True
for el in possible_combinations:
if ret_valid(el):
if "".join(el) not in valid_list:
valid_list.append("".join(el))
print(", ".join(valid_list))