惊雷无声 发表于 2025-5-16 02:29:23

LeetCode - 22 括号生成

标题泉源

22. 括号生成 - 力扣(LeetCode)

标题形貌

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

示例

示例 1:
<strong>输入:</strong>n = 3
<strong>输出:</strong>["((()))","(()())","(())()","()(())","()()()"]
示例 2:
<strong>输入:</strong>n = 1
<strong>输出:</strong>["()"]
提示



[*]1 <= n <= 8

标题剖析

本题可以通过 “回溯算法” 解题。
   回溯算法是基于递归进行的,而递归过程,可以模拟为一颗树的生成过程。

以示例1为例:
树的第一层节点生成
   每一层节点都有两种选择:左括号 "(" 或着 右括号 ")"
但是正当的括号组合,不大概以 右括号 开头,因此可以剪去 ‘)’ 分支
https://i-blog.csdnimg.cn/direct/aaf4da5521ec4cb8a6ceda6462da823f.png
树的第二层节点生成
https://i-blog.csdnimg.cn/direct/a97797142eb648d997e15572c7ce6d4b.png
树的第三层节点生成
   此时 ()) 分支被剪枝 ,由于其必然不正当。

此时我们可以总结出:
如果分支中 左括号 数目 小于 右括号 数目,则生成效果必然不正当。
https://i-blog.csdnimg.cn/direct/2f252bec72f44a079bc230033436176a.png
树的第四层生成
   此时需要留意的是,由于 n == 3,因今生成效果中最多只有3个左括号,3个右括号,因此下面绿色框分支中已经用完了左括号,下一层只能选择右括号
https://i-blog.csdnimg.cn/direct/5c6ca12c2f7e4ae1811f8ec41db9d297.png
树的第五层生成
https://i-blog.csdnimg.cn/direct/e7bdcf92f1f549f384827451764a3cd5.png
树的第六层生成,由于正当括号组合必然是以 ) 结尾,因此末了一层必然是右括号
https://i-blog.csdnimg.cn/direct/40b8418c99f84b8b8d6d9a7aa58d5fad.png

通过上面递归树的过程模拟,我们可以总结出:
递归过程中


[*]当前层可选 "左括号" 的条件是:对应分支中,左括号数目未达n个
[*]当前层可选 "右括号" 的条件是:对应分支中,左括号数目 大于 右括号数目

C源码实现

/**
* Note: The returned array must be malloced, assume caller calls free().
*/

char* path;

char** results;
int result_size;

void dfs(int index, int leftCount, int rightCount, int n) {
    if (leftCount == n && rightCount == n) { // 如果当前分支已经有了n个左括号、n个右括号,则结束递归
      results = (char*)calloc(n * 2 + 1, sizeof(char));
      strcpy(results, path);
      return;
    }

    if (leftCount < n) { // 可选左括号的条件是:当前分支中左括号数量未达n个
      path = '(';
      dfs(index + 1, leftCount + 1, rightCount, n);
    }

    if (leftCount > rightCount) { // 可选右括号的条件是:当前分支中左括号数量 > 右括号数量
      path = ')';
      dfs(index + 1, leftCount, rightCount + 1, n);
    }
}

char** generateParenthesis(int n, int* returnSize) {
    path = (char*)calloc(n * 2 + 1, sizeof(char));
    path = '('; // 第0层肯定选左括号,因为合法的括号组合不可能以右括号开头

    results = (char**)malloc(sizeof(char*) * pow(2, 16));
    result_size = 0;

    dfs(1, 1, 0, n);

    *returnSize = result_size;
    return results;
}
C++源码实现

class Solution {
public:
    vector<char> path;
    vector<string> results;

    vector<string> generateParenthesis(int n) {
      path = vector<char>(n * 2);
      path = '('; // 第0层肯定选左括号,因为合法的括号组合不可能以右括号开头

      dfs(1, 1, 0, n);

      return results;
    }

    void dfs(int index,int leftCount, int rightCount, int n) {
      if (leftCount == n && rightCount == n) { // 如果当前分支已经有了n个左括号、n个右括号,则结束递归
            string s(path.begin(), path.end());
            results.emplace_back(s);
            return;
      }

      if (leftCount < n) { // 可选左括号的条件是:当前分支中左括号数量未达n个
            path = '(';
            dfs(index + 1, leftCount + 1, rightCount, n);
      }

      if (leftCount > rightCount) { // 可选右括号的条件是:当前分支中左括号数量 > 右括号数量
            path = ')';
            dfs(index + 1, leftCount, rightCount + 1, n);
      }
    }
};
Java源码实现

class Solution {
    static char[] path;
    static ArrayList<String> results;

    public List<String> generateParenthesis(int n) {
      path = new char;
      path = '('; // 第0层肯定选左括号,因为合法的括号组合不可能以右括号开头

      results = new ArrayList<>();

      dfs(1, 1, 0, n);

      return results;
    }

    public void dfs(int index, int leftCount, int rightCount, int n) {
      if (leftCount == n && rightCount == n) { // 如果当前分支已经有了n个左括号、n个右括号,则结束递归
            results.add(new String(path));
            return;
      }

      if (leftCount < n) { // 可选左括号的条件是:当前分支中左括号数量未达n个
            path = '(';
            dfs(index + 1, leftCount + 1, rightCount, n);
      }

      if (leftCount > rightCount) { // 可选右括号的条件是:当前分支中左括号数量 > 右括号数量
            path = ')';
            dfs(index + 1, leftCount, rightCount + 1, n);
      }
    }
}
Python源码实现

class Solution(object):
    def generateParenthesis(self, n):
      """
      :type n: int
      :rtype: List
      """
      path = ['\0'] * n * 2
      path = '('

      results = []

      def dfs(index, leftCount, rightCount):
            if leftCount == n and rightCount == n:
                results.append("".join(path))
                return

            if leftCount < n:
                path = '('
                dfs(index + 1, leftCount + 1, rightCount)

            if leftCount > rightCount:
                path = ')'
                dfs(index + 1, leftCount, rightCount + 1)

      dfs(1, 1, 0)

      return results

JavaScript源码实现

/**
* @param {number} n
* @return {string[]}
*/
var generateParenthesis = function (n) {
    const path = new Array(n * 2);
    path = '('; // 第0层肯定选左括号,因为合法的括号组合不可能以右括号开头

    const results = [];

    function dfs(index, leftCount, rightCount) {
      if (leftCount == n && rightCount == n) {// 如果当前分支已经有了n个左括号、n个右括号,则结束递归
            results.push(path.join(""));
            return;
      }

      if (leftCount < n) { // 可选左括号的条件是:当前分支中左括号数量未达n个
            path = '(';
            dfs(index + 1, leftCount + 1, rightCount);
      }

      if (leftCount > rightCount) { // 可选右括号的条件是:当前分支中左括号数量 > 右括号数量
            path = ')';
            dfs(index + 1, leftCount, rightCount + 1);
      }
    }

    dfs(1, 1, 0);

    return results;
};

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: LeetCode - 22 括号生成