首页 > 其他分享 >【力扣高频题】021.括号生成

【力扣高频题】021.括号生成

时间:2024-08-16 11:23:09浏览次数:14  
标签:count index lMinusR 力扣 括号 021 ans path

上篇文章我们学习了判断一个字符串是否是有效的括号顺序 : 有效的括号 。今天我们继续来学习一道有关有效括号的 中等难度 题目。

22. 括号生成

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

示例 1:

输入: n = 3

输出: [“((()))”,“(()())”,“(())()”,“()(())”,“()()()”]

示例 2:

输入: n = 1

输出: [“()”]

  • 提示:
  • 1 <= n <= 8

思路分析

对于 n n n 对括号,需要 2 n 2n 2n 个位置来存放。

本题我们采用 从左到右 的递归来思考。考虑每个位置上能够存放什么类型的括号。

当然,最简单的思路就是枚举所有可能的情况。由于我们已经定好了总的括号数量为 2 n 2n 2n,因此只要在枚举完后检查每种枚举结果是否是有效的括号组合即可。(只要合法,数量一定是 n n n 对)

合法性检查:

  1. 维护计数变量count = 0,遍历序列,遇到左括号加一,遇到右括号减一。
  2. 若中途出现count < 0的情况,说明此时序列中,右括号多于左括号,不合法。
  3. 若遍历结束,count == 0,说明左右括号数量相等且合法,否则说明左括号多于右括号,不合法。

暴力递归

// 不剪枝
public static List<String> generateParenthesis(int n) {
   char[] path = new char[n << 1];
   List<String> ans = new ArrayList<>();
   process(path, 0, ans);
   return ans;
}

public static void process(char[] path, int index, List<String> ans) {
   if (index == path.length) {
       if (isValid(path)) {
           ans.add(String.valueOf(path));
       }
   } else {
       path[index] = '(';
       process(path, index + 1, ans);
       path[index] = ')';
       process(path, index + 1, ans);
   }
}

public static boolean isValid(char[] path) {
   int count = 0;
   for (char cha : path) {
       count = (cha == '(') ? count+1 : count-1;
       if (count < 0) {
           return false;
       }
   }
   return count == 0;
}

思路优化

对于上面的暴力递归来说,生成了许多无效的解,没有做到合理的剪枝。其原因在于,生成解的 过程中 并没有做有效性检查(把检查放在了最后)。

因此,我们考虑增加一些变量的限制,使其仅生成有效解,大大减少运算量。

在递归中增加两个参数,lMinusRleftRest

  • lMinusR表示在path[0 ... index-1]已经做过的决策中左括号-右括号的数量
  • leftRest表示还有多少左括号可以使用,即总数 n - 已经使用过的

剪枝代码

public static List<String> generateParenthesis(int n) {
   char[] path = new char[n << 1];
   List<String> ans = new ArrayList<>();
   process(path, 0, 0, n, ans);
   return ans;
}

public static void process(char[] path, int index, int lMinusR, int leftRest, List<String> ans) {
   if (index == path.length) {
       ans.add(String.valueOf(path));
   } else {
       if (leftRest > 0) {
           path[index] = '(';
           process(path, index + 1, lMinusR + 1, leftRest - 1, ans);
       }
       if (lMinusR > 0) {
           path[index] = ')';
           process(path, index + 1, lMinusR - 1, leftRest, ans);
       }
   }
}

代码分析

  1. 当下标来到最后时,生成结束,加入到答案集合中。
  2. 如果左括号还有剩余,说明此时还可以放入左括号。继续后移,此时lMinusR + 1,能够使用的左括号减少一个。
  3. 如果lMinusR > 0,说明此时可以放入右括号。继续后移,此时lMinusR - 1,能够使用的左括号不变。

小伙伴们可以再认真思考下该代码哦~~~

最后

上次给大家介绍的 面试八股文小程序 评价 杠杠滴~~

最近又和朋友一起合作开发了算法全套刷题 ,专门针对于 解决面试中算法问题 学习的课程,有需要的小伙伴可以去看看,保证你在面试中如鱼得水。

~ 点赞 ~ 关注 ~ 星标 ~ 不迷路 ~!!!
回复「1024」获取 Java 面试资源 ~
回复「ACM紫书」获取 ACM 算法书籍 ~
回复「算法导论」获取 算法导论第3版 ~

在看 + 转发

让你的小伙伴们一起来学算法吧!!

标签:count,index,lMinusR,力扣,括号,021,ans,path
From: https://blog.csdn.net/weixin_46879314/article/details/141219045

相关文章

  • 力扣 | 一维简单线性dp | 2140. 解决智力问题、322. 零钱兑换、2466. 统计构造好字符
    文章目录一、2140.解决智力问题二、322.零钱兑换三、2466.统计构造好字符串的方案数四、91.解码方法五、983.最低票价六、790.多米诺和托米诺平铺需要特别注意的题目有2140.解决智力问题和983.最低票价,因为这两个题目可以启发思路,其他的题都比较普通。一、21......
  • 力扣 | 动态规划 | 状态机 | 买卖股票 | 买卖股票的最佳时机
    文章目录一、309.买卖股票的最佳时机含冷冻期二、714.买卖股票的最佳时机含手续费三、123.买卖股票的最佳时机III四、188.买卖股票的最佳时机IV本质上这种属于动态规划题目但又有多种状态的,我们只需要正确定义出状态即可。可能每个人定义的状态不一样,但只要是对......
  • Efficient DETR:别再随机初始化了,旷视提出单解码层的高效DETR | CVPR 2021
    EfficientDETR结合密集检测和稀疏集合检测的优点,利用密集先验来初始化对象容器,弥补单层解码器结构与6层解码器结构的差距。在MSCOCO上进行的实验表明,仅3个编码器层和1个解码器层即可实现与最先进的目标检测方法竞争的性能,在CrowdHuman密集数据集上的性能也远远优于其它检......
  • SMCA:港中文提出注意力图校准的DETR加速方案 | ICCV 2021
    为了加速DETR收敛,论文提出了简单而有效的SpatiallyModulatedCo-Attention(SMCA)机制,通过在初始边界框位置给予较高的协同注意力响应值的约束来构建DETR的回归感知协同注意力。此外,将SMCA扩展为多头注意力和尺度选择注意力后,对比DETR可以实现更好的性能(108周期45.6mAPvs500周期......
  • 力扣第五十九题——螺旋矩阵II
    内容介绍给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 nxn 正方形矩阵 matrix 。示例1:输入:n=3输出:[[1,2,3],[8,9,4],[7,6,5]]示例2:输入:n=1输出:[[1]]提示:1<=n<=20完整代码classSolution{publi......
  • NSSCTF [SWPUCTF 2021 新生赛]easyupload3.0
    进入页面,是一个文件上传,放个图片马上去,用bp抓包正常进行文件上传,发现一般的后缀都被过滤了 使用.user.ini后门但好像也不行。没有什么头绪,去网上看看大佬们怎么做的。发现他们是通过修改.htaccess文件的配置来实现后门,之前也只了解过这个后缀,先去看看是干嘛的,具体怎么用。大佬......
  • 【刷力扣】876. 链表的中间结点
    876.链表的中间结点依旧是“力扣新手村”里的题,我的思路只有解法1,然而解法2更妙,学习学习!解法1:单指针法1.经过一次遍历求出链表的长度。2.再次遍历找到链表的中间结点。classSolution{public:ListNode*middleNode(ListNode*head){intsize=0;//记录链......
  • 【刷力扣】1342. 将数字变成 0 的操作次数
    1342.将数字变成0的操作次数这题是包含在“力扣新手村”里的题,按直接模拟的方法来写很简单。不过我一点儿都没有想到位运算的写法,看了看别人的题解,学习了一下下~解法1:直接模拟直接按题意模拟:1.判断num是否为0。2.num不为0,进行一次操作:(1)奇数:num=num-1;(2)偶数:num=num......
  • 力扣刷题之2940.找到Alice和Bob可能相遇的建筑
    题干描述给你一个下标从 0 开始的正整数数组 heights ,其中 heights[i] 表示第 i 栋建筑的高度。如果一个人在建筑 i ,且存在 i<j 的建筑 j 满足 heights[i]<heights[j] ,那么这个人可以移动到建筑 j 。给你另外一个数组 queries ,其中 queries[i]=[......
  • Leetcode JAVA刷刷站(20)有效的括号
    一、题目概述二、思路方向     在Java中,要判断一个仅包含括号('(',')','{','}','[',']')的字符串是否有效,你可以使用栈(Stack)数据结构来实现。栈是一种后进先出(LIFO,LastInFirstOut)的数据结构,非常适合用来处理这类问题。以下是具体的实现步骤和代码示例:创......