LeetCode100之括号生成(22)--Java

1.问题描述

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

示例1

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

示例2

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

提示

  • 1 <= n <= 8

难度等级

中等

题目链接

生成括号

2.解题思路

这道题要我们求出指定括号对数所能满足的所有可能,想法很简单,把这个过程分成无数的添加左括号和右括号的小步,每一次添加之后,判断是否是合法的括号形式,是的话就继续,不是的话就撤销回退,因为我们要穷举所有的可能,所以在每一步真正执行完成之后,都要把当前这一步撤销回退(回溯)。

这里,我们直接来看核心的递归函数是如何实现的。

首先,我们要确定递归的结束条件。如果左括号的个数大于n,或者右括号的个数大于左括号的个数,那么情况的括号形式是非法的,递归结束,不做任何操作。如果右括号的个数等于n,说明我们找到了一种符合题意的情况,将当前这种情况加入到存储结果的List集合中,然后递归结束。

java 复制代码
        //如果左括号数大于n、右括号数大于左括号数,直接返回
        if(leftSum > n || rightSum > leftSum){
            return;
        }
        //如果右括号个数等于n,递归结束
        if(rightSum == n){
            //将当前情况添加到data中
            data.add(sb.toString());
            //返回
            return;
        }

接着,我们要来确定递归的结束条件。我们需要传入题目给的括号对数n,当前左括号的个数和当前右括号的个数,以及用来存储合法可能的List集合,由于每一种可能的情况都是一个字符串,这意味着我们要不断的对字符串进行增删操作,所以这里我们可以传入一个StringBuilder来提高字符串操作的效率。

java 复制代码
public void backtrack(int n,int leftSum,int rightSum,List<String> data,StringBuilder sb)

然后,我们就可以来确定单层的递归逻辑了。其实很简单,在当前情况的基础上,添加左括号,然后递归调用当前方法,同时左括号个数+1,获取当前情况基础上所有的可能情况,获取到所有可能情况之后,将左括号从当前情况的字符串中移除(撤销回滚)。右括号的步骤和上述差不多,我就不多赘述了。

java 复制代码
        //单层递归逻辑
        //添加左括号
        sb.append('(');
        backtrack(n,leftSum+1,rightSum,data,sb);
        sb.delete(sb.length()-1,sb.length());
        //添加右括号
        sb.append(')');
        backtrack(n,leftSum,rightSum+1,data,sb);
        sb.delete(sb.length()-1,sb.length());

最后,只需要在主方法中调用我们上面实现的函数并将答案返回即可。

java 复制代码
    public List<String> generateParenthesis(int n) {
        //存储结果的List
        List<String> data = new ArrayList<>();
        //递归函数获取生成括号的对数
        backtrack(n,0,0,data,new StringBuilder());
        //返回最终答案
        return data;
    }

3.代码展示

java 复制代码
class Solution {
    public List<String> generateParenthesis(int n) {
        //存储结果的List
        List<String> data = new ArrayList<>();
        //递归函数获取生成括号的对数
        backtrack(n,0,0,data,new StringBuilder());
        //返回最终答案
        return data;
    }
    public void backtrack(int n,int leftSum,int rightSum,List<String> data,StringBuilder sb){
        //如果左括号数大于n、右括号数大于左括号数,直接返回
        if(leftSum > n || rightSum > leftSum){
            return;
        }
        //如果右括号个数等于n,递归结束
        if(rightSum == n){
            //将当前情况添加到data中
            data.add(sb.toString());
            //返回
            return;
        }
        //单层递归逻辑
        //添加左括号
        sb.append('(');
        backtrack(n,leftSum+1,rightSum,data,sb);
        sb.delete(sb.length()-1,sb.length());
        //添加右括号
        sb.append(')');
        backtrack(n,leftSum,rightSum+1,data,sb);
        sb.delete(sb.length()-1,sb.length());
    }
}

4.总结

这道题的核心的思想其实就是递归穷举,再加上一些限制条件的逻辑判断就解决了。这道题就简单的水到这里,祝大家刷题愉快~

相关推荐
jimy11 分钟前
lvalue、xvalue、prvalue(二):引用是哪一类?
开发语言·c++·1024程序员节
小豆庄2 分钟前
本地视频脱敏的追踪系统踩坑——车牌过滤、转场误判与ID冲突排查
人工智能·算法·目标检测·音视频·视频·敏捷流程·纹理贴图
忆挽篱笙歌3 分钟前
进程替换函数与shenll命令行解释器
前端·javascript·算法
cxyxixiy4 分钟前
数智码力:数据核对不用人工比对,Python 快速完成多表格差异校验
开发语言·python·学习
YukiRinLL4 分钟前
字符串存储与 BF、KMP 匹配算法
数据结构·算法
一个风轻云淡7 分钟前
从 int $0x80 到 iret:用 gdb 把 getpid 走一遍
linux·c语言·开发语言·汇编
小超人诞生日记10 分钟前
Linux:环境变量 & 进程虚拟地址空间
linux·算法
杜 硕12 分钟前
从零开始的C++生活——第三讲
开发语言·c++·生活
小白起 v17 分钟前
【算法学习 · 01】深入理解大 O 表示法:从「能跑就行」到「专业评估」算法性能
算法
梦帮科技18 分钟前
脑机接口(BCI)与神经系统安全:EEG 神经电信号欺骗注入、神经闭环解码算法与生物黑客反制
算法·安全