【每日算法】【刷穿 LeetCode】22. 括号生成(中等)

简介: 【每日算法】【刷穿 LeetCode】22. 括号生成(中等)

点击 这里 可以查看更多算法面试相关内容~


题目描述



数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且有效的括号组合。


示例 1:


输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]
复制代码


示例 2:


输入:n = 1
输出:["()"]
复制代码


提示:


  • 1 <= n <= 8


DFS 解法



既然题目是求所有的方案,那只能爆搜了,爆搜可以使用 DFS 来做。


从数据范围 1 <= n <= 8 来说,DFS 应该是稳稳的 AC。


这题的关键是我们要从题目中发掘一些性质:


  1. 括号数为 n,那么一个合法的括号组合,应该包含 n 个左括号和 n 个右括号,组合总长度为 2n
  2. 一对合法的括号,应该是先出现左括号,再出现右括号。那么意味着任意一个右括号的左边,至少有一个左括号


其中性质 2 是比较难想到的,我们可以用反证法来证明性质 2 总是成立:


假设某个右括号不满足「其左边至少有一个左括号」,即其左边没有左括号,那么这个右括号就找不到一个与之对应的左括号进行匹配。


这样的组合必然不是有效的括号组合。


使用我们「20. 有效的括号(简单)」的思路(栈)去验证的话,必然验证不通过。

掌握了这两个性质之后,我们可以设定一个初始值为 0 的得分值,令往组合添加一个 ( 得分值 + 1,往组合添加一个 ) 得分值 -1。


这样就有:


  1. 一个合法的括号组合,最终得分必然为 0 (左括号和右括号的数量相等,对应了性质 1)
  2. 整个 DFS 过程中,得分值范围在 [0, n](得分不可能超过 n 意味着不可能添加数量超过 n 的左括号,对应了性质 1;得分不可能为负数,意味着每一个右括号必然有一个左括号进行匹配,对应性质 2)


class Solution {
    public List<String> generateParenthesis(int n) {
        List<String> ans = new ArrayList<>();
        dfs(0, n * 2, 0, n, "", ans);
        return ans;
    }
    /**
    * i: 当前遍历到位置
    * n: 字符总长度
    * score: 当前得分,令 '(' 为 1, ')' 为 -1
    * max: 最大得分值
    * path: 当前的拼接结果
    * ans: 最终结果集
    */
    void dfs(int i, int n, int score, int max, String path, List<String> ans) {
        if (i == n) {
            if (score == 0) ans.add(path);
        } else {
            if (score + 1 <= max) dfs(i + 1, n, score + 1, max, path + "(", ans);
            if (score - 1 >= 0) dfs(i + 1, n, score - 1, max, path + ")", ans);
        }
    }
}
复制代码


  • 时间复杂度:放置的左括号数量为 n,右括号的个数总是小于等于左括号的个数,典型的卡特兰数问题。复杂度为 O(C2nn)O(C_{2n}^n)O(C2nn)
  • 空间复杂度:O(1)O(1)O(1)


最后



这是我们「刷穿 LeetCode」系列文章的第 No.22 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先将所有不带锁的题目刷完。


在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。


由于 LeetCode 的题目随着周赛 & 双周赛不断增加,为了方便我们统计进度,我们将按照系列起始时的总题数作为分母,完成的题目作为分子,进行进度计算。当前进度为 22/1916


为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:Github 地址 & Gitee 地址


在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和一些其他的优选题解。

相关文章
|
3月前
|
算法 Go 索引
【LeetCode 热题100】回溯:括号生成 & 组合总和(力扣22 / 39 )(Go语言版)
本文深入解析了LeetCode上的两道经典回溯算法题:**22. 括号生成**与**39. 组合总和**。括号生成通过维护左右括号数量,确保路径合法并构造有效组合;组合总和则允许元素重复选择,利用剪枝优化搜索空间以找到所有满足目标和的组合。两者均需明确路径、选择列表及结束条件,同时合理运用剪枝策略提升效率。文章附有Go语言实现代码,助你掌握回溯算法的核心思想。
96 0
|
11月前
|
算法
Leetcode 初级算法 --- 数组篇
Leetcode 初级算法 --- 数组篇
106 0
|
10月前
|
存储 算法 Java
leetcode算法题-有效的括号(简单)
【11月更文挑战第5天】本文介绍了 LeetCode 上“有效的括号”这道题的解法。题目要求判断一个只包含括号字符的字符串是否有效。有效字符串需满足左括号必须用相同类型的右括号闭合,并且左括号必须以正确的顺序闭合。解题思路是使用栈数据结构,遍历字符串时将左括号压入栈中,遇到右括号时检查栈顶元素是否匹配。最后根据栈是否为空来判断字符串中的括号是否有效。示例代码包括 Python 和 Java 版本。
203 4
|
11月前
|
算法
每日一道算法题(Leetcode 20)
每日一道算法题(Leetcode 20)
103 2
|
11月前
|
算法 C++
Leetcode第二十二题(括号生成)
这篇文章讨论了如何使用递归算法解决LeetCode第22题“括号生成”的问题,提供了两种C++的实现方法,目的是生成所有有效的括号组合。
96 0
Leetcode第二十二题(括号生成)
LeetCode第22题括号生成
该文章介绍了 LeetCode 第 22 题括号生成的解法,通过回溯算法生成所有可能的括号组合,在递归过程中根据左右括号数量的条件进行剪枝,从而得到有效的括号组合。
LeetCode第22题括号生成
|
11月前
|
存储 C++ 容器
Leetcode第二十题(有效的括号)
这篇文章介绍了如何使用栈来解决LeetCode第20题“有效的括号”问题,提供了两种方法:数组栈和容器栈,以及相应的C++代码实现。
78 0
|
算法 Java
LeetCode经典算法题:矩阵中省份数量经典题目+三角形最大周长java多种解法详解
LeetCode经典算法题:矩阵中省份数量经典题目+三角形最大周长java多种解法详解
144 6
|
存储 算法
LeetCode第20题有效的括号
该文章介绍了 LeetCode 第 20 题有效的括号的解法,通过分析有效括号的特征,使用栈结构存储括号关系,判断遇到右边括号时栈顶是否有匹配的左边括号,从而解决问题,同时总结了栈的先进后出结构可用于解决有规律的符号匹配问题。
LeetCode第20题有效的括号
|
人工智能 算法 Java
LeetCode经典算法题:井字游戏+优势洗牌+Dota2参议院java解法
LeetCode经典算法题:井字游戏+优势洗牌+Dota2参议院java解法
144 1

热门文章

最新文章