嵌套类递归

news/2024/10/6 15:45:39/文章来源:https://www.cnblogs.com/sprinining/p/18449114

嵌套类递归

  • 都需要一个全局变量记录当前正在处理的位置

基础计算器 III

  • 含有嵌套的表达式求值,时间复杂度 O(n)
#include <iostream>
#include <string>
#include <vector>using namespace std;class Solution {
public:int where;int calculate(string &s) {where = 0;return recursive(s, 0);}// 计算 s 中从 i 位置开始到他对应的右括号结束的位置int recursive(string &s, int i) {int cur = 0;// 数字栈vector<int> numbers;// 符号栈vector<char> ops;while (i < s.length()) {if (s[i] >= '0' && s[i] <= '9') {// 解析数字cur = cur * 10 + s[i++] - '0';} else if (s[i] == '(') {// 遇到左括号,递归处理下一段表达式cur = recursive(s, i + 1);// 从 where + 1 的位置继续解析i = where + 1;} else if (s[i] == ')') {// 遇到右括号就退出循环break;} else {// 遇到运算符,把解析好的数字和这个运算符入栈,cur 清零push(numbers, ops, cur, s[i++]);cur = 0;}}// 最后一个数字,由于遇不到下一个运算符,所以要手动入栈push(numbers, ops, cur, '+');// 已经处理到的位置where = i;// 计算这一对括号内的表达式return compute(numbers, ops);}void push(vector<int> &numbers, vector<char> &ops, int cur, char op) {int n = numbers.size();if (n == 0 || ops.back() == '+' || ops.back() == '-') {// 栈空或者栈顶是加减运算符,就直接放入numbers.push_back(cur);ops.push_back(op);} else {// 栈顶是乘除运算,先弹出一个数字运算后,把结果入栈int topNumber = numbers.back();char topOp = ops.back();if (topOp == '*') {numbers[n - 1] = topNumber * cur;} else {numbers[n - 1] = topNumber / cur;}ops[n - 1] = op;}}// 计算剩下的加减运算int compute(const vector<int> &numbers, const vector<char> &ops) {int n = numbers.size();int ans = numbers[0];for (int i = 1; i < n; i++)ans += ops[i - 1] == '+' ? numbers[i] : -numbers[i];return ans;}
};int main() {string s = "6-4/2*(3-1)+(2+1)*(5-3*2+(4/2+2))";Solution solution;cout << solution.calculate(s);
}
  • 递归(推荐),index++ 跳过左括号,而不是用 where + 1 去跳过
#include <iostream>
#include <string>
#include <vector>using namespace std;class Solution {
public:// 处理到的位置int index;int calculate(string &s) {return recursive(s);}// 计算 s 中从 index 位置开始到他对应的右括号结束的位置int recursive(string &s) {int cur = 0;// 数字栈vector<int> numbers;// 符号栈vector<char> ops;for (; index < s.length(); index++) {if (s[index] >= '0' && s[index] <= '9') {// 解析数字cur = cur * 10 + s[index] - '0';} else if (s[index] == '(') {// 跳过左括号index++;// 递归处理下一段表达式cur = recursive(s);} else if (s[index] == ')') {// 遇到右括号就退出循环break;} else {// 遇到运算符,把解析好的数字和这个运算符入栈,cur 清零push(numbers, ops, cur, s[index]);cur = 0;}}// 最后一个数字,由于遇不到下一个运算符,所以要手动入栈push(numbers, ops, cur, '+');// 计算这一对括号内的表达式return compute(numbers, ops);}void push(vector<int> &numbers, vector<char> &ops, int cur, char op) {int n = numbers.size();if (n == 0 || ops.back() == '+' || ops.back() == '-') {// 栈空或者栈顶是加减运算符,就直接放入numbers.push_back(cur);ops.push_back(op);} else {// 栈顶是乘除运算,先弹出一个数字运算后,把结果入栈int topNumber = numbers.back();char topOp = ops.back();if (topOp == '*') {numbers[n - 1] = topNumber * cur;} else {numbers[n - 1] = topNumber / cur;}ops[n - 1] = op;}}// 计算剩下的加减运算int compute(const vector<int> &numbers, const vector<char> &ops) {int n = numbers.size();int ans = numbers[0];for (int j = 1; j < n; j++)ans += ops[j - 1] == '+' ? numbers[j] : -numbers[j];return ans;}
};int main() {string s = "6-4/2*(3-1)+(2+1)*(5-3*2+(4/2+2))";Solution solution;cout << solution.calculate(s);
}

394. 字符串解码

  • 含有嵌套的字符串解码,时间复杂度 O(n)
  • 从第一个右括号开始解析,从里向外解析每一对括号,解析成字符串后入栈,继续找下个右括号
#include <iostream>
#include <string>
#include <vector>
#include <stack>using namespace std;class Solution {
public:string decodeString(string s) {stack<char> stk;// 用于逆序输出栈中内容deque<char> deq;for (int i = 0; i < s.size(); ++i) {// 右括号前的全部入栈while (i < s.size() && s[i] != ']') {stk.emplace(s[i]);i++;}// 已经到字符串 s 的结尾了if (s[i] != ']') break;// 解析括号内的字符串string tempStr;while (stk.top() != '[') {deq.emplace_front(stk.top());stk.pop();}while (!deq.empty()) {tempStr += deq.front();deq.pop_front();}// 弹出 '['stk.pop();// 解析左括号前的数字,也就是括号内字符的重复次数int count = 0;while (!stk.empty() && stk.top() >= '0' && stk.top() <= '9') {deq.emplace_front(stk.top());stk.pop();}while (!deq.empty()) {count *= 10;count += deq.front() - '0';deq.pop_front();}// 记录重复 count 次的字符串string repeated;for (int j = 0; j < count; ++j)repeated.append(tempStr);// 重新入栈for (auto &c: repeated)stk.emplace(c);}// 全部出栈string res;deq.clear();while (!stk.empty()) {deq.emplace_front(stk.top());stk.pop();}while (!deq.empty()) {res += deq.front();deq.pop_front();}return res;}
};
  • 用两个栈分别记录左括号之前的数字,以及数字前的字符串。每次遇到右括号就把括号内重复相应次数,然后与这个数字之前的字符串拼接
class Solution {
public:// "abc2[a2[c]t]2[k]xyz";// abcacctacctkkxyzstring decodeString(const string &s) {// 临时记录数字int multi = 0;// 临时记录数字前的字符串string str;stack<int> stack_multi;stack<string> stack_str;for (char c: s) {if (c == '[') {// 遇到左括号,说明左括号前的数字已经被确定,存入栈中stack_multi.emplace(multi);// 数字之前的字符串也确定了,存入栈中stack_str.emplace(str);// 清空这两个临时变量multi = 0;str.clear();} else if (c == ']') {// 取出当前括号内字符串应该重复的次数int cur_multi = stack_multi.top();stack_multi.pop();// 重复对应的次数后记录到tmp中string tmp;for (int i = 0; i < cur_multi; i++) tmp += str;// 再接到之前数字前已经出现的字符串后面str = stack_str.top() + tmp;stack_str.pop();} else if (c >= '0' && c <= '9') {// 确定重复次数multi = multi * 10 + (c - '0');} else {// 记录数字前的字符串,或者是括号内的字符串str.push_back(c);}}return str;}
};
  • 递归
#include <string>using namespace std;class Solution {
public:int where;string recursive(string s, int i) {string str;int multi = 0;while (i < s.length() && s[i] != ']') {if (s[i] >= '0' && s[i] <= '9') {// 解析重复次数multi = 10 * multi + s[i++] - '0';} else if (s[i] == '[') {// 递归处理下一段string repeatedStr = recursive(s, i + 1);// 重复 multi 次,并且接在 str 后面while (multi > 0) {str += repeatedStr;multi--;}i = where + 1;} else {// 解析数字前的字符串,或者括号内的字符串str += s[i++];}}where = i;return str;}string decodeString(string s) {where = 0;return recursive(s, 0);}
};
  • 递归(推荐),index++ 跳过左括号,而不是用 where + 1 去跳过
#include <string>using namespace std;class Solution {
public:// 当前处理位置的下标int index = 0;string decodeString(string s) {string str;int multi = 0;for (; index < s.size(); index++) {if (s[index] >= '0' && s[index] <= '9') {// 解析重复次数multi = 10 * multi + s[index] - '0';} else if (s[index] == '[') {// 跳过这个左括号index++;// 递归处理括号内的字符串string repeatedStr = decodeString(s);// 重复 multi 次,并且接在 str 后面while (multi > 0) {str += repeatedStr;multi--;}} else if (s[index] == ']') {// 结束递归,返回括号内的字符串break;} else {// 解析数字前的字符串,或者括号内的字符串str += s[index];}}return str;}
};

726. 原子的数量

  • 含有嵌套的分子式求原子数量,时间复杂度 O(n)
  • 处理过程
    • 遇到字母:解析出元素符号,以及该元素出现次数
    • 遇到左括号 (:递归处理这段括号的分子式,从左括号一直到右括号后面的数字
    • 遇到右括号 ):如果右括号后面是数字,则需要乘对应倍数
#include <string>
#include <iostream>
#include <map>using namespace std;class Solution {
public:// 分子式中处理到的下标int index;bool isNumber(char ch) {return ch >= '0' && ch <= '9';}bool isLowercaseLetter(char ch) {return ch >= 'a' && ch <= 'z';}bool isUppercaseLetter(char ch) {return ch >= 'A' && ch <= 'Z';}// 返回原子出现次数map<string, int> recursive(string &formula) {// 有序 mapmap<string, int> freq;while (index < formula.length()) {if (isUppercaseLetter(formula[index])) {// 化学元素符号由一个大写字母或者一个大写字母加若干个小写字母确定string atom = "";atom += formula[index++];// 先生成完整的元素符号,如果后面是小写字母就追加上去while (index < formula.length() && isLowercaseLetter(formula[index]))atom += formula[index++];// 判断这个元素符号出现的次数int cnt = 0;if (index < formula.length() && isNumber(formula[index])) {while (index < formula.length() && isNumber(formula[index]))cnt = cnt * 10 + formula[index++] - '0';} else {// 只出现一次cnt = 1;}freq[atom] += cnt;} else if (formula[index] == '(') {index++;// 递归处理这段括号的分子式,从左括号一直到右括号后面的数字map<string, int> tempCount = recursive(formula);// 累加出现次数for (const auto &item: tempCount)freq[item.first] += item.second;// 结束后 index 为下一个非数字的字符的下标,继续从 index 开始处理} else if (formula[index] == ')') {index++;// 如果右括号后面是数字,则需要乘对应倍数if (index < formula.length() && isNumber(formula[index])) {int cnt = 0;while (index < formula.length() && isNumber(formula[index]))cnt = cnt * 10 + formula[index++] - '0';for (auto &item: freq)freq[item.first] = item.second * cnt;}// 返回这一段分子式的元素统计return freq;}}return freq;}string countOfAtoms(string formula) {index = 0;map<string, int> count = recursive(formula);string res;// 从有序 map 中生成结果字符串for (const auto &item: count) {res.append(item.first);if (item.second != 1)res.append(to_string(item.second));}return res;}
};

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

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

相关文章

Java - 11 类与对象

Java - 11 类与对象 类 类[属性, 行为] ->对象[属性, 行为] public class Test{public static void main(String[] args){Cat cat1 = new Cat(); // 创建对象cat1.name = "大宝";cat1.age = "3";cat1.color = "orange";System.out.println(ca…

20222413 2024-2025-1 《网络与系统攻防技术》实验一实验报告

1.实验内容 在本周的学习过程中,我了解到了许多缓冲区溢出攻击的实际案例、缓冲区溢出攻击的原理和相关基础知识,包括GDB调试器的使用方法、反汇编、基础的汇编语言与指令等,重新温习了函数调用过程和进程管理方面的知识内容。并且通过实验一,我能够了解并熟练完成Linux系统…

函数的上下文

函数的上下文 概述 在函数体的语句中,会出现this这个词,this就是函数的上下文 函数中this是谁,就说明函数的上下文是谁 函数中的this是谁,要看是如何调用的,因为this不是一成不变的 比如我们看下面的例子 var obj = {a: 100,fun: function() {console.log(this.a);} };我们…

拥挤聚集智能监测系统

拥挤聚集智能监测系统可以通过对人员数量、密度等进行实时监测,拥挤聚集智能监测系统识别出拥挤聚集的情况,并及时发出预警。拥挤聚集智能监测系统可以通过对人员进车间的人数等进行监测,识别出是否存在人员拥堵、挤压等安全隐患,及时发出警报,提醒工作人员采取措施疏散人…

睡岗识别 AI助力企业安全管控

睡岗识别可以通过AI视频智能分析技术,睡岗识别识别出操作人员是否存在睡岗情况。例如,在变电站等场景中,睡岗识别技术可以通过对识别出操作人员是否存在睡岗情况,及时发出预警,避免因操作人员的疏忽而导致的安全事故。在工厂车间中,睡岗识别技术可以通过对工人的行为进行…

加油站安全风险监测预警系统

加油站安全风险监测预警系统可以通过对加油站设备、环境、人员等方面进行监测,加油站安全风险监测预警系统实现对加油站的全面监管。例如,在加油站油罐区中,加油站安全风险监测预警系统可以对加油站人员抽烟打电话、明火烟雾等环境安全隐患进行自动识别,及时发出预警,避免…

山西煤矿电子封条

山西煤矿电子封条通过AI视觉分析技术,山西煤矿电子封条实现对各矿区(煤矿和非煤矿区)每日矿井出入井人监察控制、调度室空岗识别、煤矿生产作业状态、摄像头遮挡、挪动角度识别、货运车辆出矿识别等。山西煤矿电子封条实现当前待办事项的推送,以及对各矿区用户区域内的报警…

离岗识别 AI助力企业安全管控

离岗识别通过yolov5网络模型技术,离岗识别可以自动识别办公室、工厂、监控室监控画面中人员离岗脱岗睡岗等行为,发现违规行为立即抓拍告警并同步睡岗离岗等违规数据到后台提醒值班人员及时处理。离岗识别采用人工智能算法识别技术对各主控室、办公室、工厂、煤矿监控室等人员…

登高作业安全带穿戴识别系统 - 保障登高作业人员安全

登高作业安全带穿戴识别系统是一种通过Ai视觉智能分析技术,登高作业安全带穿戴识别系统实现对登高作业人员是否穿戴安全带进行监测的系统,登高作业安全带穿戴识别系统通过视频监控智能识别技术检测登高作业人员是否佩戴安全带,并及时发出警报,以提醒工作人员及时穿戴安全带…

MySQL单表存多大的数据量比较合适

前言 经常使用MySQL数据库的小伙伴都知道,当单表数据量达到一定的规模以后,查询性能就会显著降低。因此,当单表数据量过大时,我们往往要考虑进行分库分表。那么如何计算单表存储多大的数据量合适?当单表数据达到多大的规模时,我们才要进行分库分表呢? MySQL存储方式 首先…

【THM】kiba练习

脚本小子是这样的,黑客只要写POC就可以,可是脚本小子要考虑的事情就多了。 学到了新知识:利用网上的POC进行复现、利用Capabilities进行提权【THM】kiba练习 与本文相关的TryHackMe实验房间链接:TryHackMe | kiba 简介:识别数据可视化仪表板中允许执行远程代码执行的关键…

信息学奥赛复赛复习13-CSP-J2021-02插入排序-排序稳定性、插入排序、sort排序、结构体、计数排序

PDF文档公众号回复关键字:202410061P7910 [CSP-J 2021] 插入排序 [题目描述] 插入排序是一种非常常见且简单的排序算法。小 Z 是一名大一的新生,今天 H 老师刚刚在上课的时候讲了插入排序算法。 假设比较两个元素的时间为 O(1),则插入排序可以以 O(n^2) 的时间复杂度完成长度…