题目:
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:
链接: http://leetcode.com/problems/generate-parentheses/
题解:
一样也是一道回溯题,可以dfs + 回溯,也可以用dp做。
下面是回溯。 Time Complexity - n * Catalan number (n) ~ O(4n), Space Complexity O(n2)
public class Solution { public List<String> generateParenthesis(int n) { List<String> res = new ArrayList<>(); if(n <= 0) return res; String str = new String(); dfs(res, str, n, n); return res; } private void dfs(List<String> res, String str, int leftP, int rightP) { if(leftP > rightP) return; if(leftP == 0 && rightP == 0) { res.add(new String(str)); return; } if(leftP >= 0) dfs(res, str + '(', leftP - 1, rightP); if(rightP >= 0) dfs(res, str + ')', leftP, rightP - 1); } }
下面是DP解法,来自discussion的left.peter
一开始初始化Lists.get(0) = "", 之后对之前的lists做类似catalab number的操作 Cn = Σni=0 Ci Cn - i
Time Complexity - O(4n), Space Complexity - O(n2)
public class Solution { public List<String> generateParenthesis(int n) { List<List<String>> lists = new ArrayList(); lists.add(Collections.singletonList("")); for(int i = 1; i <= n; i++) { List<String> list = new ArrayList(); for(int j = 0; j < i; j++) for(String first : lists.get(j)) for(String second : lists.get(i - 1 - j)) list.add("(" + first + ")" + second); lists.add(list); } return lists.get(lists.size() - 1); } }
二刷:
Java:
这道题目一刷做得马马虎虎,现在来还债。 题目就是给定正整数n,求可以生成的括号的组合。这里我们采用dfs + backtracking,用来作buffer的StringBuilder里,先写入左括号,回溯,再写入右括号,回溯。计算Space Complexity的时候没有考虑最后的结果List
Time Complexity - O(2n), Space Complexity - O(n)
public class Solution { public List<String> generateParenthesis(int n) { List<String> res = new ArrayList<>(); if (n <= 0) { return res; } StringBuilder sb = new StringBuilder(); generateParenthesis(res, sb, n, n); return res; } private void generateParenthesis(List<String> res, StringBuilder sb, int leftCount, int rightCount) { if (leftCount > rightCount) { return; } if (leftCount == 0 && rightCount == 0) { res.add(sb.toString()); return; } if (leftCount >= 0) { sb.append('('); generateParenthesis(res, sb, leftCount - 1, rightCount); sb.setLength(sb.length() - 1); } if (rightCount >= 0) { sb.append(')'); generateParenthesis(res, sb, leftCount, rightCount - 1); sb.setLength(sb.length() - 1); } } }
Python:
class Solution(object): def generateParenthesis(self, n): """ :type n: int :rtype: List[str] """ list = [] str = "" self.getParenthesis(list, str, n, n) return list def getParenthesis(self, list, str, leftCount, rightCount): if leftCount > rightCount: return if leftCount == 0 and rightCount == 0: list.append(str) return if leftCount >= 0: self.getParenthesis(list, str + '(', leftCount - 1, rightCount) if rightCount >= 0: self.getParenthesis(list, str + ')', leftCount, rightCount - 1)
三刷:
方法和二刷一样,就是在dfs里面使用两个变量leftCount和rightCount来决定如何加括号。 注意在加括号前要判断leftCount和rightCount是否大于0, 并且之后要注意回溯。
Java:
Time Complexity - O(2n), Space Complexity - O(n)
public class Solution { public List<String> generateParenthesis(int n) { List<String> res = new ArrayList<>(); if (n <= 0) return res; generateParenthesis(res, new StringBuilder(), n, n); return res; } private void generateParenthesis(List<String> res, StringBuilder sb, int leftCount, int rightCount) { if (rightCount < leftCount) return; if (leftCount == 0 && rightCount == 0) res.add(sb.toString()); if (leftCount > 0) { generateParenthesis(res, sb.append("("), leftCount - 1, rightCount); sb.setLength(sb.length() - 1); } if (rightCount > 0) { generateParenthesis(res, sb.append(")"), leftCount, rightCount - 1); sb.setLength(sb.length() - 1); } } }
Reference:
https://leetcode.com/discuss/11509/an-iterative-method
https://leetcode.com/discuss/14436/concise-recursive-c-solution
https://leetcode.com/discuss/25063/easy-to-understand-java-backtracking-solution
https://leetcode.com/discuss/18162/my-accepted-java-solution
https://leetcode.com/discuss/71960/ms-beats-92%25-submissions-easy-java-space-optimized-solution
https://leetcode.com/discuss/66868/clean-python-dp-solution
https://leetcode.com/discuss/50698/my-java-code-using-dp