一.问题描述
Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.
For example, given n = 3, a solution set is:
[ "((()))", "(()())", "(())()", "()(())", "()()()" ]
二.解题思路
这道题解法其实很简单,首先可以明确的一点是,第一个括号肯定是左括号。
然后我们需要探究的是,什么时候,一个字符串不是一个合适的括号匹配呢。
仔细观察我们可知,一个完整的括号匹配字符串,是在每个字符串位置i,它的前i个括号中,左括号的个数一定是大于或等于右括号数的。因为这样子我们能保证每一个右括号都有一个左括号与之匹配,所以它能满足题意(因为对于任意的左括号,即使左括号个数大于右括号,在之后出现的右括号能与多出的左括号匹配,也可以用反证法很容易证明)。反之,如果前i个括号中,左括号个数小于右括号个数,说明有某个有括号不能被左括号匹配,然而之后出现的左括号不能与前面落单的右括号匹配,因为不能形成一个完成的括号。
方法一:深度优先搜索
至于实现的话,可以用递归来做。其实说白了就是一个深度优先搜索。
递归最重要的一点就是决定递推规则,
假设当前我的字符串是s,那么对于下个括号的选择,有两个,左括号和右括号,对应不同的情况。
1.左括号数>=右括号数,此时s+左括号和右括号都可以。根据剩余左括号或右括号数分别进行递归。
2.左括号数<右括号数,此时不能形成一个完整的括号字符串,剪枝,返回空。
3.左括号数和右括号数都等于0,说明一个可行的括号字符串形成,加到结果中。
用迭代实现的话会稍微麻烦一点。迭代就深度优先搜索。
时间复杂度:O(NN).
方法二:动态规划
一共有n个括号对要生成,假设我们知道所有第一对,第二对,....,第n-1对完整括号序列,
对于第n对括号的生成,我们只需要对所有满足i+j=n-1的i和j,将第i对括号的生成序列+ ( + 第j对括号生成序列 + ),即是第n对括号所有的完整序列。
更直观的理解,假设现在有n-1的完整括号序列,我们从里面添加一个左括号和右括号使得其生成一个n对完整序列。
其实就是遍历每个可能放置左括号和右括号的位置,只要保证先+左括号,再加右括号就没问题。
详情可以看代码。
更多leetcode算法题解法: 专栏 leetcode算法从零到结束 或者 leetcode 解题目录 Python3 一步一步持续更新~
三.源码
1.递归
class Solution:
def generateParenthesis(self, n: int) -> List[str]:
def generateParenthesisHelper(string,n_left,n_right,rst):
if n_left>n_right:return
if n_left==0 and n_right==0:
rst.append(string)
if n_left!=0:
generateParenthesisHelper(string+'(',n_left-1,n_right,rst)
if n_right!=0:
generateParenthesisHelper(string+')',n_left,n_right-1,rst)
if n==0:return []
rst=[]
generateParenthesisHelper("(",n-1,n,rst)
return rst
#version 2 再做简化
class Solution:
def generateParenthesis(self, n: int) -> List[str]:
def dfs(left, right, state):
if right==n:
f.append(state)
return
if left<n:
dfs(left+1, right, state+'(')
if left>right:
dfs(left, right+1, state+')')
f = []
dfs(0, 0, '')
return f
2.动态规划,代码来自官方示例。
class Solution:
def generateParenthesis(self, n: int) -> List[str]:
dp = {}
dp[0] = [""]
if n > 0:
for i in range(1,n+1):
dp[i] = []
for j in range(i):
for p in dp[j]:
for q in dp[i-j-1]:
dp[i].append(p+"("+q + ")")
return dp[n]