news 2026/1/19 6:43:26

算法题 括号的分数

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
算法题 括号的分数

856. 括号的分数

问题描述

给定一个平衡括号字符串s,按下述规则计算该字符串的分数:

  • ()得 1 分
  • ABA + B分,其中AB是平衡括号字符串
  • (A)2 * A分,其中A是平衡括号字符串

返回字符串s的分数。

示例

输入:"()"输出:1
输入:"(())"输出:2解释:(())=2*()=2*1=2
输入:"()()"输出:2解释:()()=()+()=1+1=2
输入:"(()(()))"输出:6解释:(()(()))=2*(()+(()))=2*(1+2)=6

算法思路

深度优先搜索 + 栈模拟

  1. 核心

    • 平衡括号字符串可以递归分解
    • 每个()贡献的分数 = 2^(深度)
  2. 方法一:递归

    • 遍历字符串,找到每个独立的平衡子串
    • 对每个子串递归计算分数
    • 合并结果:独立子串相加,嵌套子串乘以2
  3. 方法二:深度计算

    • 遍历字符串,维护当前深度
    • 遇到()时,贡献分数为 2^depth
    • 每个()的实际贡献等于它所在深度的2的幂次
  4. 方法三:栈模拟

    • 使用栈存储当前各层的分数
    • 遇到(时压入0
    • 遇到)时,计算当前层分数并更新上一层

代码实现

方法一:递归

classSolution{/** * 递归计算括号字符串的分数 * 将字符串分解为独立的平衡子串,分别计算后相加 * * @param s 平衡括号字符串 * @return 字符串的分数 */publicintscoreOfParentheses(Strings){returnscore(s,0,s.length()-1);}/** * 计算子串s[start...end]的分数 */privateintscore(Strings,intstart,intend){// 基础情况:最简单的"()"得1分if(end-start==1){return1;}intbalance=0;// 平衡计数器inttotalScore=0;// 找到独立的平衡子串并分别计算for(inti=start;i<=end;i++){if(s.charAt(i)=='('){balance++;}else{balance--;}// 当balance为0时,找到了一个独立的平衡子串if(balance==0){if(i==end){// 整个字符串是一个嵌套结构:(A)// 分数 = 2 * score(A)totalScore=2*score(s,start+1,end-1);}else{// 当前子串是独立的:AB 形式// 分数 = score(A) + score(B)totalScore+=score(s,start,i);// 递归处理剩余部分totalScore+=score(s,i+1,end);break;// 已经分解完成}}}returntotalScore;}}

方法二:深度计算

classSolution{/** * 深度计算 * 每个"()"的贡献是2^depth,其中depth是其嵌套深度 * * @param s 平衡括号字符串 * @return 字符串的分数 */publicintscoreOfParentheses(Strings){intdepth=0;// 当前嵌套深度inttotalScore=0;// 总分数for(inti=0;i<s.length();i++){if(s.charAt(i)=='('){depth++;}else{depth--;// 如果前一个字符是'(',说明遇到了"()"if(s.charAt(i-1)=='('){// 贡献分数为2^depthtotalScore+=(1<<depth);// 位运算:1 << depth = 2^depth}}}returntotalScore;}}

方法三:栈模拟

importjava.util.*;classSolution{/** * 使用栈模拟计算括号分数 * 栈中存储当前各层的累计分数 * * @param s 平衡括号字符串 * @return 字符串的分数 */publicintscoreOfParentheses(Strings){Stack<Integer>stack=newStack<>();stack.push(0);// 初始化栈底为0for(charc:s.toCharArray()){if(c=='('){// 遇到左括号,压入0表示新层开始stack.push(0);}else{// 遇到右括号,计算当前层的分数intcurrentScore=stack.pop();// 当前层的分数intparentScore=stack.pop();// 父层的分数// 如果currentScore为0,说明是"()",得1分// 否则是嵌套结构,得2 * currentScore分intlayerScore=currentScore==0?1:2*currentScore;// 将当前层分数加到父层stack.push(parentScore+layerScore);}}// 栈中只剩最终结果returnstack.pop();}}

算法分析

  • 方法一时间复杂度:O(n²)
    • 最坏情况下每次递归都要遍历整个子串
    • 例如:(((((...)))))这样的完全嵌套结构
  • 方法二时间复杂度:O(n)
    • 只需要一次遍历
    • 位运算操作是O(1)
  • 方法三时间复杂度:O(n)
    • 每个字符最多入栈出栈一次
  • 空间复杂度
    • 方法一:O(n)(递归栈)
    • 方法二:O(1)
    • 方法三:O(n)(显式栈)

算法过程

1:s = "(()(()))"

方法二

s: ( ( ) ( ( ) ) ) i: 0 1 2 3 4 5 6 7
  1. i=0(depth=1
  2. i=1(depth=2
  3. i=2)depth=1,前一个字符是(,所以totalScore += 2^1 = 2
  4. i=3(depth=2
  5. i=4(depth=3
  6. i=5)depth=2,前一个字符是(,所以totalScore += 2^2 = 4
  7. i=6)depth=1,前一个字符是),不加分
  8. i=7)depth=0,前一个字符是),不加分

结果totalScore = 2 + 4 = 6

方法三

初始: stack = [0] ( : stack = [0, 0] ( : stack = [0, 0, 0] ) : pop 0, pop 0 → 0==0 → push 0+1 = [0, 1] ( : stack = [0, 1, 0] ( : stack = [0, 1, 0, 0] ) : pop 0, pop 0 → 0==0 → push 0+1 = [0, 1, 1] ) : pop 1, pop 1 → 1!=0 → push 1+2*1 = [0, 3] ) : pop 3, pop 0 → 3!=0 → push 0+2*3 = [6] 结果: 6

测试用例

publicclassMain{publicstaticvoidmain(String[]args){Solutionsolution=newSolution();// 测试用例1:基础情况System.out.println("Test 1: "+solution.scoreOfParentheses("()"));// 1// 测试用例2:嵌套System.out.println("Test 2: "+solution.scoreOfParentheses("(())"));// 2// 测试用例3:并列System.out.println("Test 3: "+solution.scoreOfParentheses("()()"));// 2// 测试用例4:复杂嵌套System.out.println("Test 4: "+solution.scoreOfParentheses("(()(()))"));// 6// 测试用例5:深度嵌套System.out.println("Test 5: "+solution.scoreOfParentheses("((()))"));// 4// ((())) = 2 * (2 * ()) = 2 * 2 * 1 = 4// 测试用例6:混合结构System.out.println("Test 6: "+solution.scoreOfParentheses("()(())"));// 3// ()(()) = 1 + 2 = 3// 测试用例7:更复杂System.out.println("Test 7: "+solution.scoreOfParentheses("(()()())"));// 6// (()()()) = 2 * (1 + 1 + 1) = 6// 测试用例8:最大深度System.out.println("Test 8: "+solution.scoreOfParentheses("((((()))))"));// 16// 2^4 = 16// 测试用例9:单层多并列System.out.println("Test 9: "+solution.scoreOfParentheses("()()()()"));// 4// 测试用例10:嵌套和并列混合System.out.println("Test 10: "+solution.scoreOfParentheses("((())(()))"));// 8// ((())(())) = 2 * (2 + 2) = 8}}

关键点

  1. 深度贡献

    • 每个()的实际贡献是2^depth
    • 每嵌套一层,外层的括号会将内层分数乘以2
  2. 识别()

    • 在遍历时,如果当前字符是)且前一个字符是(,说明遇到了基础的()
  3. 位运算

    • 1 << depthMath.pow(2, depth)更高效
    • 位运算在底层执行更快

常见问题

  1. 为什么每个()的贡献是 2^depth?
    每层外层括号都会将内层分数乘以2。例如,深度为2的()会被外层两层括号分别乘以2,总共乘以4=2²。

  2. 方法二如何处理()()这种并列情况?
    每个()都会被独立识别和计算。第一个()在深度0时贡献1,第二个()也在深度0时贡献1,总共2。

  3. 栈中的初始0?
    初始0作为根节点的分数,确保所有计算都有父层可以累加。最终栈中只剩这个累加后的总分数。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/15 6:17:04

4-12路模拟量采集模块:电网智能的“精准核心”

高精度模拟量采集模块是电力系统数字化与保护控制的核心感知单元&#xff0c;负责将PT/CT二次侧电压/电流、温度、振动等模拟量转为高保真数字量&#xff0c;支撑保护速动、计量结算、状态监测与新能源并网控制&#xff0c;在变电站、发电厂、配网与储能/光伏/风电场站广泛落地…

作者头像 李华
网站建设 2026/1/16 19:05:10

空气质量监测不精准?高精度模拟量采集模块给出智能家居解决方案

高精度模拟量采集模块是智能家居系统的核心感知单元&#xff0c;负责将温湿度、光照、气体浓度、人体感应、能耗等模拟信号&#xff0c;转化为高保真数字信号&#xff0c;为家电联动、节能控制、安全防护提供精准数据支撑&#xff0c;让家居从“被动响应”升级为“主动智能”&a…

作者头像 李华
网站建设 2026/1/17 15:53:26

【新】基于SSM的旅游攻略网站【源码+文档+调试】

&#x1f495;&#x1f495;发布人&#xff1a; 星河码客 &#x1f495;&#x1f495;个人简介&#xff1a;混迹java圈十余年&#xff0c;精通Java、小程序、数据库等。 &#x1f495;&#x1f495;各类成品Java毕设 。javaweb&#xff0c;ssm&#xff0c;springboot等项目&…

作者头像 李华
网站建设 2026/1/17 7:12:02

一台solidworks工作站带动5人同时流畅三维设计和办公如何实现

在传统的工作站模式下&#xff0c;企业不仅面临硬件投入大&#xff0c;而且存在资源利用率低、数据安全隐患等问题。而通过部署共享云桌面解决方案&#xff0c;一台solidworks工作站带动5人同时流畅三维设计和办公&#xff0c;这种创新模式正在重塑行业的工作方式。那么该如何实…

作者头像 李华
网站建设 2026/1/16 18:56:10

如何用Open-AutoGLM 9b实现低延迟推理?:一线专家总结的4步落地法

第一章&#xff1a;Open-AutoGLM 9b低延迟推理概述Open-AutoGLM 9b 是一款面向高效自然语言处理场景设计的开源大语言模型&#xff0c;专为实现低延迟、高吞吐量的推理任务而优化。该模型在保持强大语义理解能力的同时&#xff0c;通过结构压缩、算子融合与硬件感知调度等技术手…

作者头像 李华
网站建设 2026/1/17 2:57:42

为什么90%的开发者首次部署Open-AutoGLM都会踩坑?:避坑指南速看

第一章&#xff1a;Open-AutoGLM部署前的环境准备与认知重塑在着手部署 Open-AutoGLM 之前&#xff0c;必须重新审视本地开发环境的技术栈匹配度与资源分配策略。该模型对计算资源、依赖版本及系统权限有明确要求&#xff0c;任何疏漏都可能导致部署失败或运行不稳定。环境依赖…

作者头像 李华