算法-嵌套类递归解题套路

文章目录

    • 理论基础 :
    • 1. 基本计算器
    • 2. 字符串解码
    • 3. 求原子数量

理论基础 :

嵌套类递归是指一种一个字符串形式的问题通过嵌套调用子函数从而求解出结果的一类问题, 解题方法相对来说比较的固定, 我们总结为下面的几部分
大概过程 :

  1. 定义全局变量where
  2. 递归函数 f ( i ) : s [ i …] 从 i 位置开始解析, 遇到 字符串终止 或者是 嵌套条件终止 就返回
  3. 返回值是 f ( i ) 负责的这一段的结果
  4. f ( i ) 在返回前更新全局变量where, 目的是告诉上级函数我们以及解析到了什么位置, 从而继续函数的调用
  5. 执行细节 :
    5.1 : 如果 f ( i ) 遇到嵌套条件开始, 就调用下级的递归去处理嵌套, 下级会负责嵌套部分的计算结果
    5.2 : f ( i ) 下级处理后, f ( i ) 可以根据下级更新的全局变量where, 知道该从什么新的位置开始继续解析的过程
    下面是几道例题来验证我们的理论基础

1. 基本计算器

在这里插入图片描述

这道题是一道典型的嵌套类问题, 用递归求解的思路
我们先来看一种比较简单的情况, 就是不涉及括号的式子
举例 1 + 3 - 6 * 2 / 3 + 8 + 9 - 10
图例如下
其实就是做一个数字栈与符号栈, 我们要实现的效果是 :
当遇到 ’ + ’ 或者是 ’ - ’ 的时候就直接入符号栈, 当遇到数字的时候, 要判断符号栈栈顶的元素是不是 ’ * ’ 或者是 ’ / ’ , 如果不是的话直接入栈, 如果是的话, 就从数字栈中弹出一个元素, 然后与当前数字运算完之后的结果入数字栈, 我们把上面的过程用图描述如下

在这里插入图片描述

这道题用我们嵌套类递归的解题思路就是下面描述的一样
我们举下面的例子
在这里插入图片描述
代码实现如下

class Solution {public int calculate(String s) {//首先处理字符串s(去除空格)String ss = s.replace(" ","");return func(ss.toCharArray(),0);}//定义的全局变量whereprivate int where = 0;//计算的主方法 func(char[] ss, int index)private int func(char[] exp, int i){//首先每一个主方法的内部都有自己的cur(值), 数字栈, 符号栈LinkedList<Integer> numstack = new LinkedList<>();LinkedList<Character> opstack = new LinkedList<>();int cur = 0;//加入不满足while循环的条件就直接停止了while(i < exp.length && exp[i] != ')'){if(exp[i] >= '0' && exp[i] <= '9'){//说明是数字cur = cur * 10 + (exp[i++] - '0');}else if(exp[i] != '('){//说明是操作符号push(numstack,opstack,cur,exp[i++]);cur = 0;}else{//说明是左括号(进入递归)cur = func(exp, i + 1);i = where + 1;}}//走到这一步说明该部分的所有数字已经被收集完毕, 开始进行算数运算(并更新当前的全局where)numstack.add(cur);where = i;return compute(numstack,opstack);}//计算的方法(我们的计算方法设计的和左神不太一样, 我们设计的是数字比符号多一个private int compute(LinkedList<Integer> numstack, LinkedList<Character> opstack){if(numstack.size() < 1) return 0;while(!opstack.isEmpty()){int left = numstack.removeFirst();int right = numstack.removeFirst();char op = opstack.removeFirst();numstack.addFirst(op == '+' ? left + right : left - right);}return numstack.pop();}//压入数字进入操作数栈的方法private void push(LinkedList<Integer> numstack, LinkedList<Character> opstack, int cur, char op){if(numstack.isEmpty() || opstack.isEmpty() || opstack.getLast() == '+' || opstack.getLast() == '-'){numstack.add(cur);opstack.add(op);}else{if(opstack.removeLast() == '*'){numstack.add(numstack.removeLast() * cur);}else{numstack.add(numstack.removeLast() / cur);}}}
}

2. 字符串解码

在这里插入图片描述

这道题的思路跟上面的那个题是一致的, 就是对嵌套的处理逻辑是不一样的, 代码实现如下

class Solution {public int index = 0;public String decodeString(String s) {char[] ch = s.toCharArray();return defunc(ch, 0);}//表示从i位置处开始解码private String defunc(char[] ch, int i){int cur = 0;StringBuilder sp = new StringBuilder();//如果不满足下面的条件说明递归已经可以结束了while(i < ch.length && ch[i] != ']'){if(ch[i] >= '0' && ch[i] <= '9'){//说明是数字就更新数字cur = cur * 10 + (ch[i++] - '0');}else if(ch[i] == '['){String res = defunc(ch, i + 1);for(int j = 0; j < cur; ++j){sp.append(res);}cur = 0;i = index + 1;}else{sp.append(ch[i++]);}}index = i;return sp.toString();}
}

3. 求原子数量

在这里插入图片描述

这个题跟基本计算器返回的不一样的点就是, 我们最终返回的是一个TreeMap, 即每一个嵌套里面的原子数量的情况, 然后最后对这个红黑树进行遍历就可以得解

class Solution {/*** 原子的数量, 还是我们之前学习的那个递归的思路* 定义一个全局变量变量遍历的where;*/private int where = 0;public String countOfAtoms(String formula) {//把字符串转化为字符数组char[] ch = formula.toCharArray();TreeMap<String, Integer> map = func(ch, 0);//进行拼接收尾处理StringBuilder sp = new StringBuilder();for(Map.Entry<String,Integer> elem : map.entrySet()){sp.append(elem.getKey());sp.append(elem.getValue() == 1 ? "" : elem.getValue());}return sp.toString();}//我们的主函数func返回的是一个TreeMap的原子集合public TreeMap<String, Integer> func(char[] ch, int i) {//下面是基础的所需准备TreeMap<String, Integer> map = new TreeMap<>();StringBuilder sp = new StringBuilder();String scur = null;int cur = 0;//当我们不满足下面的条件的时候就会自动跳出来while (i < ch.length && ch[i] != ')') {if (ch[i] >= 'A' && ch[i] <= 'Z') {sp.append(ch[i++]);while (i < ch.length && ch[i] >= 'a' && ch[i] <= 'z') {sp.append(ch[i++]);}//如果中了if, 说明一定只有一个字符, 那么就直接入树if (i == ch.length || ch[i] >= 'A' && ch[i] <= 'Z'|| ch[i] == '(' || ch[i] == ')') {map.put(sp.toString(), map.getOrDefault(sp.toString(), 0) + 1);}else{scur = sp.toString();}//清空sp字符串拼接函数sp.delete(0, sp.length());} else if(i < ch.length && ch[i] >= '0' && ch[i] <= '9'){//如果是数字就先进行数字的拼接, 然后进行上面留下来的字符串的添加while(i < ch.length && ch[i] >= '0' && ch[i] <= '9'){cur = cur * 10 + ch[i++] - '0';}map.put(scur, map.getOrDefault(scur, 0) + cur);cur = 0;scur = null;} else {//这里就只能碰上左括号了TreeMap<String,Integer> tempMap = func(ch, i + 1);//对来自内部的消息进行解析(更新下标的值)i = where + 1;int tempCur = 0;while(i < ch.length && ch[i] >= '0' && ch[i] <= '9'){tempCur = tempCur * 10 + ch[i++] - '0';}//对拿到的TreeMap的值进行倍增操作if(tempCur != 0){for(Map.Entry<String,Integer> elem : tempMap.entrySet()){map.put(elem.getKey(),map.getOrDefault(elem.getKey(), 0) + tempCur * elem.getValue());}}else{for(Map.Entry<String,Integer> elem : tempMap.entrySet()){map.put(elem.getKey(),map.getOrDefault(elem.getKey(), 0) + elem.getValue());}}}}//退出之后记得更新全局的下标的位置where = i;return map;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/382255.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C++】——初识模版

文章目录 前言函数模版函数模版的原理函数模版的实例化 类模版类模版的实例化 前言 当我们使用一个通用的函数&#xff1a; //为每一个类型都编写一个重载版本 void Swap(int& left, int& right) {int temp left;left right;right temp; } void Swap(double& …

C# 与C++ cli

cli CLI&#xff08;Command Line Interface&#xff09;是一种通过命令行界面与计算机系统进行交互的方式。它提供了一种以文本形式输入命令和接收系统输出的方法&#xff0c;用于执行各种操作和管理计算机系统。以下是CLI的详细解释&#xff1a; 一、定义与基本概念 定义&…

编程中的智慧四:设计模式总览

前面三篇我们通过从一些零散的例子&#xff0c;和简单应用来模糊的感受了下设计模式在编程中的智慧&#xff0c;从现在开始正式进入设计模式介绍&#xff0c;本篇将从设计模式的7大原则、设计模式的三大类型、与23种设计模式的进行总结&#xff0c;和描述具体意义。 设计模式体…

【中项】系统集成项目管理工程师-第4章 信息系统架构-4.5技术架构

前言&#xff1a;系统集成项目管理工程师专业&#xff0c;现分享一些教材知识点。觉得文章还不错的喜欢点赞收藏的同时帮忙点点关注。 软考同样是国家人社部和工信部组织的国家级考试&#xff0c;全称为“全国计算机与软件专业技术资格&#xff08;水平&#xff09;考试”&…

关卡1-2:Python关卡

关卡1-2&#xff1a;Python关卡 一、python实现wordcount二、通过本地VSCODE连接internStudio与debug2.1使用本地的VSCODE连接InternStudio2.2 debug插件安装2.3 debug进行时2.3.1 代码准备2.3.2 选择python解释器2.3.3 打断点 一、python实现wordcount 采用python实现经典任务…

虚拟机迁移报错:虚拟机版本与主机“x.x.x.x”的版本不兼容

1.虚拟机在VCenter上从一个ESXi迁移到另一个ESXi上时报错&#xff1a;虚拟机版本与主机“x.x.x.x”的版本不兼容。 2.例如从10.0.128.13的ESXi上迁移到10.0.128.11的ESXi上。点击10.0.128.10上的任意一台虚拟机&#xff0c;查看虚拟机版本。 3.确认要迁移的虚拟机磁盘所在位…

大厂面试-基本功

大厂面试第4季 服务可用性多少个9是什么意思遍历集合add或remove操作bughashcode冲突案例BigdecimalList去重复IDEA Debugger测试框架ThreaLocal父子线程数据同步 InheritableThreadLocal完美解决线程数据同步方案 TransmittableThreadLocal 服务可用性多少个9是什么意思 遍历集…

Android中systrace配置及注意问题

Android中systrace配置及注意问题 systrace配置的官方文档地址如下&#xff1a;优化启动时间 Systrace systrace 允许在启动期间收集内核和 Android 跟踪记录。systrace 的可视化可以帮助分析启动过程中的具体问题。&#xff08;不过&#xff0c;如果要查看整个启动过程中的平…

[Spring] Spring配置文件

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏: &#x1f9ca; Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 &#x1f355; Collection与…

DocRED数据集

DocRED数据集文件夹包含多个JSON文件&#xff0c;每个文件都有不同的用途。以下是这些文件的用途解释以及哪个文件是训练集&#xff1a; 文件解释 dev.json&#xff1a;包含开发集&#xff08;验证集&#xff09;的数据&#xff0c;通常用于模型调优和选择超参数。 label_map…

Java | Leetcode Java题解之第260题只出现一次的数字III

题目&#xff1a; 题解&#xff1a; class Solution {public int[] singleNumber(int[] nums) {int xorsum 0;for (int num : nums) {xorsum ^ num;}// 防止溢出int lsb (xorsum Integer.MIN_VALUE ? xorsum : xorsum & (-xorsum));int type1 0, type2 0;for (int n…

Java 中的异常

异常&#xff1a;就是出现的问题。 在Java中异常被当成对象进行处理&#xff0c;所有的异常类都继承于Throwable类&#xff0c;如果Java提供的异常类并不能满足需求&#xff0c;用户还可以自己定义一个异常类。 下面是异常体系结构&#xff1a; Throwable又分成了Error和Exce…

PHP框架详解- symfony框架

文心一言 Symfony框架是一个用PHP语言编写的开放源代码的Web应用框架&#xff0c;旨在加速Web应用程序的开发过程&#xff0c;提高代码的可维护性和可扩展性。以下是对Symfony框架的详细解析&#xff1a; 一、框架概述 起源与开发者&#xff1a; Symfony由SensioLabs&#…

音乐曲谱软件Guitar Pro 8.2 for Mac 中文破解版

Guitar Pro 8.2 for Mac 中文破解版是一款功能强大的音乐曲谱软件&#xff0c;非常适合学习如何玩&#xff0c;改进技巧&#xff0c;重现喜爱的歌曲或陪伴自己。 Guitar Pro for Mac 是一款功能强大的音乐曲谱软件&#xff0c;非常适合学习如何玩&#xff0c;改进技巧&#xf…

宠物经济纵深观察:口红效应显著,呈可持续发展态势

七月以来&#xff0c;全国各地陆续开启高温模式。和人一样&#xff0c;“毛孩子们”同样也难耐高温&#xff0c;由此&#xff0c;围绕猫猫狗狗的“宠物经济”迅速升温&#xff0c;宠物冰垫、宠物饮水机、宠物烘干机......一系列宠物单品掀起夏日消费热潮。 就在几天前&#xf…

Pytorch学习笔记day4——训练mnist数据集和初步研读

该来的还是来了hhhhhhhhhh&#xff0c;基本上机器学习的初学者都躲不开这个例子。开源&#xff0c;数据质量高&#xff0c;数据尺寸整齐&#xff0c;问题简单&#xff0c;实在太适合初学者食用了。 今天把代码跑通&#xff0c;趁着周末好好的琢磨一下里面的各种细节。 代码实…

这7款高效爬虫工具软件,非常实用!

在当今数据驱动的时代&#xff0c;自动化爬虫工具和软件成为了许多企业和个人获取数据的重要手段。这里会介绍6款功能强大、操作简便的自动化爬虫工具&#xff0c;用好了可以更高效地进行数据采集。 1. 八爪鱼采集器 八爪鱼是一款功能强大的桌面端爬虫软件&#xff0c;主打可…

pico+unity3d 射线交互教程

前期配置&#xff1a;环境配置参考教程一&#xff0c;手部模型参考教程二&#xff0c;场景基于上一篇搭建。 最终效果&#xff1a;手部射线&#xff08;初始不可见&#xff09;对准 UI 显示&#xff0c;按下手柄 Trigger 键与可交互 UI&#xff08;如 Button、Toggle、Slider …

数学建模(7)——Logistic模型

一、马尔萨斯人口模型 import numpy as np import matplotlib.pyplot as plt# 初始人口 N0 100 # 人口增长率 r 0.02 # 时间段&#xff08;年&#xff09; t np.linspace(0, 200, 200)# 马尔萨斯人口模型 N N0 * np.exp(r * t)# 绘图 plt.plot(t, N, labelPopulation) plt.…

【源码阅读】Sony的go breaker熔断器源码探究

文章目录 背景源码分析总结 背景 在微服务时代&#xff0c;服务和服务之间调用、跨部门调用都是很常见的事&#xff0c;但这些调用都存在很多不确定因素&#xff0c;如核心服务A依赖的部门B服务挂掉了&#xff0c;那么A本身的功能将会受到直接的影响&#xff0c;而这些都会影响…