news 2026/6/10 15:23:36

hot100 22.括号生成

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
hot100 22.括号生成

思路:回溯。本质上来说,我们需要在0,1,2,...,2n - 1中选n个数(位置),填入左括号。其余n个位置填入右括号。所以本题是有额外约束的组合问题,对于括号字符串的任意前缀,右括号的个数不能超过左括号的个数,比如())(就是不合法的。

一、方法一:枚举当前位置填左括号还是右括号。

1.本质:是“选或不选”的思想,可以把填左括号视作“选”,填右括号视作“不选”。

2.递归的过程中,要保证右括号的个数不能超过左括号的个数。

(1)如果现在右括号的个数等于左括号的个数,那么不能填右括号。

(2)如果现在右括号的个数小于左括号的个数,那么可以填右括号。

(3)如果左括号的个数始终大于等于右括号的个数,且至多填n个左括号,所以当我们填了n个右括号时,也一定填了n个左括号,此时填完了所有2n个括号。

3.疑问:什么时候需要写恢复现场,什么时候不需要写恢复现场?

答:

在下面的代码中,如果初始化path为空列表,那么就需要写恢复现场。本题由于所有的括号长度都是固定的2n,我们可以创建一个长为2n的path列表,在递归时直接写入字符(而不是插入字符),这样做无需写恢复现场。

4.复杂度分析:

(1)时间复杂度:分析回溯问题的时间复杂度,有一个通用公式:路径长度×搜索树的叶子数。对于本题,它等于O(n⋅C(2n,n))。但由于左右括号的约束,实际上没有那么多叶子,根据Catalan数,只有C(2n,n)/(n+1)个叶子节点,所以实际的时间复杂度为O(C(2n,n))。此外,根据阶乘的 Stirling公式,时间复杂度也可以表示为O(4^n/根号n)。

(2)空间复杂度:O(n)。返回值的空间不计入。

附代码:

class Solution { public List<String> generateParenthesis(int n) { List<String> res = new ArrayList<>(); char[] path = new char[n*2]; // 所有括号组合长度都是2n dfs(0,0,n,path,res); // 一开始没有填括号 return res; } // 目前填了left个左括号,right个右括号 private void dfs(int left,int right,int n,char[] path,List<String> res){ if(right == n){ // 填完了2n个括号 res.add(new String(path)); return; } if(left < n){ // 可以填左括号 path[left + right] = '('; // 直接覆盖,避免了显式恢复现场 dfs(left + 1,right,n,path,res); } if(right < left){ // 可以填右括号 path[left + right] = ')'; // 直接覆盖,避免了显式恢复现场 dfs(left,right + 1,n,path,res); } } }

​二、方法二:枚举下一个左括号的位置。

1.思路:用“枚举选哪个”的思路,也就是说在从左往右填的过程中,要时刻保证右括号的个数不能超过左括号的个数。

2.举例:如果前面填了5个左括号,2个右括号,那么至多还能填3个右括号。

所以,在填下一个左括号之前,枚举填入了0,1,2,3个右括号,这样就能得到下一个左括号的位置。

3.为了方便,代码直接使用balance表示左右括号之差,这样枚举的范围就是[0,balance]。

4.注意:最后一个左括号的右边还可以填右括号,但无需考虑。填入所有左括号后,剩余的位置我们会自动填入右括号。

5.复杂度分析:

(1)时间复杂度:分析回溯问题的时间复杂度,有一个通用公式:路径长度×搜索树的叶子数。对于本题,它等于O(n⋅C(2n,n))。但由于左右括号的约束,实际上没有那么多叶子,根据Catalan数,只有C(2n,n)/(n+1)个叶子节点,所以实际的时间复杂度为O(C(2n,n))。此外,根据阶乘的 Stirling公式,时间复杂度也可以表示为O(4^n/根号n)。

(2)空间复杂度:O(n)。返回值的空间不计入。

附代码:

class Solution { public List<String> generateParenthesis(int n) { List<String> res = new ArrayList<>(); List<Integer> path = new ArrayList<>(); dfs(0,0,n,path,res); return res; } // 目前填了i个括号 // 这i个括号中的左括号个数 - 右括号个数 = balance private void dfs(int i,int balance,int n,List<Integer> path,List<String> res){ if(path.size() == n){ char[] s = new char[n*2]; Arrays.fill(s,')'); for(int j : path){ s[j] = '('; } res.add(new String(s)); return; } // 枚举填right = 0,1,2,......,balance个右括号 for(int right = 0;right <= balance;right++){ // 先填right个右括号,然后填1个左括号,记录左括号的下标 i + right path.add(i + right); dfs(i + right + 1,balance - right + 1,n,path,res); path.removeLast(); // path.remove(path.size() - 1); } } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 12:40:07

乔尔·格林布拉特的价值投资实践指南

乔尔格林布拉特的价值投资实践指南 关键词:乔尔格林布拉特、价值投资、实践指南、投资策略、财务分析 摘要:本文围绕乔尔格林布拉特的价值投资理念展开,旨在为投资者提供一套全面的价值投资实践指南。通过介绍价值投资的背景知识,阐述核心概念与联系,深入剖析核心算法原理…

作者头像 李华
网站建设 2026/5/19 20:07:39

大数据领域特征工程助力企业数据决策

大数据领域特征工程助力企业数据决策——从原始数据到商业洞察的魔法桥梁关键词&#xff1a;特征工程、大数据、企业数据决策、特征提取、特征选择、特征构造、数据价值转化摘要&#xff1a;在企业数据决策的战场上&#xff0c;原始数据就像未加工的矿石&#xff0c;而特征工程…

作者头像 李华
网站建设 2026/6/9 22:24:15

社会网络仿真软件:UCINET_(6).基本网络度量指标

基本网络度量指标 在社会网络分析中&#xff0c;网络度量指标是用于描述网络结构和节点特性的关键工具。这些指标可以帮助我们理解网络中的节点关系、中心性、聚类和路径等特性。UCINET提供了多种网络度量指标的计算功能&#xff0c;通过这些指标&#xff0c;用户可以深入分析…

作者头像 李华
网站建设 2026/6/7 22:47:57

到底什么是企业采购数字化转型?——协同型 SRM 才是关键

谢邀 &#xff0c;大家都在说采购数字化转型&#xff0c;那到底什么是企业采购数字化转型&#xff1f; 可以先问自己几个问题&#xff1a; 你们企业的采购流程&#xff0c;是不是已经上线系统了&#xff1f;审批已经电子化了&#xff1f;供应商的报价、交期、合同都在线吗&am…

作者头像 李华