LeetCode 22. 括号生成【字符串,回溯;动态规划】中等

本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章中,我不仅会讲解多种解题思路及其优化,还会用多种编程语言实现题解,涉及到通用解法时更将归纳总结出相应的算法模板。

为了方便在PC上运行调试、分享代码文件,我还建立了相关的仓库:https://github.com/memcpy0/LeetCode-Conquest。在这一仓库中,你不仅可以看到LeetCode原题链接、题解代码、题解文章链接、同类题目归纳、通用解法总结等,还可以看到原题出现频率和相关企业等重要信息。如果有其他优选题解,还可以一同分享给他人。

由于本系列文章的内容随时可能发生更新变动,欢迎关注和收藏征服LeetCode系列文章目录一文以作备忘。

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

示例 1:

输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]

示例 2:

输入:n = 1
输出:["()"]

提示:

  • 1 <= n <= 8

解法 暴力递归(生成 2 2 n 2^{2n} 22n 个序列)

每个位置可以使用 ( 或者 ) ,因此总共有 2 2 n 2^{2n} 22n 个序列。我们全部生成出来,然后检查每个是否有效即可。

为了生成所有序列,我们可以使用递归。长度为 n n n 的序列就是在长度为 n − 1 n - 1 n1 的序列前加一个 ()

为了检查序列是否有效,我们遍历这个序列,并使用一个变量 balance \textit{balance} balance 表示左括号的数量减去右括号的数量。如果在遍历过程中 balance \textit{balance} balance 的值小于零,或者结束时 balance \textit{balance} balance 的值不为零,那么该序列就是无效的,否则它是有效的。

class Solution {
   
private:
    vector<string> ans;
    bool valid(const string& s) {
   
        int balance = 0;
        for (char c : s) {
   
            if (c == '(') ++balance;
            else --balance;
            if (balance < 0) return false;
        }
        return balance == 0;
    }
    void dfs(string& s, int n) {
   
        if (n == s.size()) {
   
            if (valid(s)) ans.push_back(s); // 检查是否有效序列
            return;
        }
        s += '(';
        dfs(s, n);
        s.pop_back();
        s += ')';
        dfs(s, n);
        s.pop_back();
    }
public:
    vector<string> generateParenthesis(int n) {
   
        string current;
        dfs(current, n * 2);
        return ans;
    }
};

复杂度分析:

  • 时间复杂度: O ( 2 2 n n ) O(2^{2n}n) O(22nn) ,对于 2 2 n 2^{2n} 22n 个序列中的每一个,我们用于建立和验证该序列的复杂度为 O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n) ,除了答案数组之外,我们所需要的空间取决于递归栈的深度,每一层递归函数需要 O ( 1 ) O(1) O(1) 的空间,最多递归 2 n 2n
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

memcpy0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值