leetcode 22——括号生成

题目:在这里插入图片描述

方法一:深度优先遍历(dfs)

思路:

不难看出,此题目的解空间树是一棵高度为n的满二叉树,按照深度优先遍历的方法,搜索所有的叶子节点,再去判断哪些是符合条件的解,返回即可,这是不难想到的。

但是,这道题目显然是可以进行剪枝的,观察一下解空间树的中间节点,可以发现只要当前节点中的右括号比左括号多,那这个分支下的叶子节点就不可能是正确的解,因此,用left代表剩余的’(’,用right代表剩余的’)’,如果left>right,直接返回即可

代码:

class Solution {
    public List<String> generateParenthesis(int n) {
        List<String> ans = new ArrayList();
        if(n==0) return ans;
        dfs(ans,"",n,n);
        return ans;
    }
    void dfs(List<String> ans, String cur, int left , int right){
        if(left==0 && right==0){
            ans.add(cur);
            return;
        }
        if(left>right) 
            return;
        if(left>0) 
            dfs(ans,cur+'(',left-1,right);
        if(right>0)
            dfs(ans,cur+')',left,right-1);
    }
}

方法二:动态规划

思路:

仅就这道题目而言,动态规划其实从时间和空间的复杂度上来说,都要比dfs来的更加复杂,但是动态规划是应当掌握的一种重要方法,应用动态规划的前提有两个:

1.最优子结构: 一个最优化策略的子策略总是最优的

2.无后效性: 如果在某个阶段上过程的状态已知,则从此阶段以后过程的发展变化仅与此阶段的状态有关,而与过程在此阶段以前的阶段所经历过的状态无关。

显然,这个问题满足以上的条件,可以使用动态规划

定义一个动态规划数组dp, 使得dp[i]表示当n==i时,所有的正确的解的集合, 因此dp中的每个元素都是一个List<String>

动态规划的核心在于状态转移方程,对于此问题,状态转移方程如下:

dp[i] = ‘(’ + dp[j]+ ‘)’ + dp[i-j-1] ( j=0,1,2…i-1)

代码:

public class Solution {

    // 把结果集保存在动态规划的数组里

    public List<String> generateParenthesis(int n) {
        if (n == 0) {
            return new ArrayList<>();
        }
        
        List<List<String>> dp = new ArrayList<>(n);

        List<String> dp0 = new ArrayList<>();
        dp0.add("");
        dp.add(dp0);

        for (int i = 1; i <= n; i++) {
            List<String> cur = new ArrayList<>();
            for (int j = 0; j < i; j++) {
                List<String> str1 = dp.get(j);
                List<String> str2 = dp.get(i - 1 - j);
                for (String s1 : str1) {
                    for (String s2 : str2) {
                        cur.add("(" + s1 + ")" + s2);
                    }
                }
            }
            dp.add(cur);
        }
        return dp.get(n);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值