leetcode 22/300 括号生成 py
1 题目说明
2 方法一:递归建树,虽然易懂但是不好写
class Solution:
def generateParenthesis(self, n: int) -> List[str]:
if n <= 0: return []
res = []
#深度优先建树,du'qi
def dfs(paths, left, right):
if left > n or right > left: return
#left和right分别代表左右括号的数量,因此对数量超过n或者对数不匹配的进行去除
if len(paths) == n * 2: # 因为括号都是成对出现的,退出递归的条件
res.append(paths)
return
dfs(paths + '(', left + 1, right) # 生成一个就加一个
dfs(paths + ')', left, right + 1)
dfs('', 0, 0)
return res
3 方法二:动态规划
class Solution:
def generateParenthesis(self, n: int) -> List[str]:
if n == 0:
return []
total_l = []
total_l.append([None]) # 0组括号时记为None
total_l.append(["()"]) # 1组括号只有一种情况,若为1,则下面循环不会开始
for i in range(2,n+1): # 开始计算i组括号时的括号组合,这里为n+1才能算到n
l = [] #l初始为空,记录每次的情况
for j in range(i):
# 开始遍历 p q (p为在第i个括号的内部的,q是在第i个括号外部的详看下面连接),其中p+q=i-1 在中间和在右边的括号之和是i-1个,因为第i个括号提前写成了(见e1), j 作为索引
now_list1 = total_l[j] # p = j 时的括号组合情况,这是记录了n=j时的括号的组合情况
#每一步都用到了前面的情况,前面的所有组成都是在新的括号的左边或者中间。
now_list2 = total_l[i-1-j] # q = (i-1) - j 时的括号组合情况
for k1 in now_list1:
for k2 in now_list2:
if k1 == None:#若为第0个,为空
k1 = ""
if k2 == None:
k2 = ""
el = "(" + k1 + ")" + k2#看k1记录在中间的括号,k2记录在括号左边的(外面的括号)
l.append(el) # 把所有可能的情况添加到 l 中
total_l.append(l) # l这个list就是i组括号的所有情况,添加到total_l中,继续求解i=i+1的情况
return total_l[n]#返回n组括号的情况
'''
作者:yuyu-13
链接:https://leetcode-cn.com/problems/generate-parentheses/solution/zui-jian-dan-yi-dong-de-dong-tai-gui-hua-bu-lun-da/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
'''
简单来说,在求N个括号的排列组合时,把第N种情况(也就是N个括号排列组合)视为单独拿一个括号E出来,剩下的N-1个括号分为两部分,P个括号和Q个括号,P+Q=N-1,然后这两部分分别处于括号E内和括号E的右边,各自进行括号的排列组合。由于我们是一步步计算得到N个括号的情况的,所以小于等于N-1个括号的排列组合方式我们是已知的(用合适的数据结构存储,方便后续调用,且在存储时可利用特定数据结构实现题目某些要求,如排序,去重等),且P+Q=N-1,P和Q是小于等于N-1的,所以我们能直接得到P个和Q个括号的情况,进而得到N个括号的结果!
这个算法主要的基点就是将排列组合的情况分为了括号内和括号外这两种情况,且仅存在两种情况!至于为什么,原因在于楼主的算法的前提是单独拿出来的括号E的左边在N个括号所有排列组合情况中都是处于最左边,所以不存在括号位于括号E的左边的情况。因此,N-1个括号(拿出了括号E)仅可能分布于括号E内和括号E外,分为两种子情况讨论! 这种思想还可以应用于其他类似的题的求解中,即怎样合理高效的利用前面步骤的计算结果得出当前步骤结果,从而得出最终结果。
若还不理解可以以n=2进行计算。
本文来自博客园,作者:xingye_z,转载请注明原文链接:https://www.cnblogs.com/xyzhrrr/p/15541665.html