Leetcode 22. Generate Parentheses解题思路

本文探讨了括号生成问题的不同解决方法,包括暴力法、回溯+剪枝法及动态规划法。暴力法生成所有可能的括号组合再进行筛选;回溯+剪枝法则在生成过程中排除非法组合;动态规划法则将问题分解为子问题,通过递归求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:

Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.

Example 1:

Input: n = 3
Output: ["((()))","(()())","(())()","()(())","()()()"]

方法1: brute force

假设我现在有个空篮子可以用来装括号,我先不管这个篮子的括号是否有效,每次我选开括号"(“或者闭括号”)"。选完后再判断篮子的括号是否有效。一共有 2 2 n 2^{2n} 22n个字符串。

时间复杂度 O ( 2 2 n ∗ n ) = O ( 4 n n ) O(2^{2n} * n) = O(4^nn) O(22nn)=O(4nn)
空间复杂度 4 n n 4^nn 4nn

方法2: 回溯 + 剪枝

回溯的概念举个例子,我面前有好几条路,每条路走完需要体力 t 0 t_0 t0。每次走完一条路,我都要把体力调整回 t 0 t_0 t0才能走完其他路。

剪枝就是很多路我不用走,或者走到一半就知道此路不通,可以回原地。

方法1是通过拿到所有的括号后判断是否有效,优化的策略是能不能之前排出那些绝对无效的组合,或者直走那些可能有效的路。

经过观察我们发现,

  1. 只要开括号的数量 < n, 我们可以一直加开括号
  2. 闭括号的数量 < 开括号的数量时,我们才能加闭括号
class Solution {
    public List<String> generateParenthesis(int n) {
        List<String> ans = new ArrayList<>();
        
        dfs(n, 0, 0, new StringBuilder(), ans);
        
        return ans;
    }
    
    public void backtrack(int n, int open, int close, StringBuilder comb, List<String> combs){
        if(open == n && close == n){
            combs.add(comb.toString());
            return;
        }
        
        if(open < n){
            comb.append("(");
            backtrack(n, open + 1, close, comb, combs);
            comb.deleteCharAt(comb.length() - 1);
        }
        if(open > close){
            comb.append(")");
            backtrack(n, open, close + 1, comb, combs);
            comb.deleteCharAt(comb.length() - 1);
        }
    }
}

方法3: 动态规划dp

一个有效的括号字符串从开括号"(“开始,对应的闭括号”)“在字符串中的某处,可以写成”(left)right"。left, right也都是有效的括号字符串。假设n = 3, 此时已经有一组括号了,剩下的2组括号由left和right共同决定,如果left提供0组有效括号字符串,那么right提供2组。如果left提供1组有效括号字符串,那么right提供1组。因此,如果left提供c组,那么right提供n - 1 - c组, 同时我们要遍历n - 1,得出left能提供的所有组数。

一个大问题分解成了一系列子问题。这就是dp的思路。

下面是伪代码

def func(n):
	if n = 0
		return [""]
	ans = []
	for c in range(n)
		for left in func(c)
			for right in func(n - 1 - c)
				ans.add("({left}){right}")
return ans
				

Java

class Solution {
    public List<String> generateParenthesis(int n) {
        
        
        List<String> ans = new ArrayList<>();
        
        if (n == 0){
            ans.add("");
            return ans;
        }

        for(int i = 0; i < n; i++){
            for(String left: generateParenthesis(i)){
                for(String right: generateParenthesis(n - 1 - i)){
                    ans.add(String.format("(%s)%s", left, right));
                }
            }
        }
        return ans;
        
        
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值