当前位置: 首页 > news >正文

暑期算法训练.14

目录

61 力扣 1042 删除字符串中的所有相邻重复项

61.1 题目解析:

61.2 算法思路:

61.3 代码演示:

61.4 总结反思

62. 力扣844 比较含退格的字符串

62.1 题目解析:

62.2 算法思路:

62.3 代码演示:

62.4 总结反思

63 力扣227 基本计算器

63.1 题目解析:

63.2 算法思路:

63.3 代码演示:

63.4 总结反思

64 力扣394 字符串解码

64.1 题目解析:

64.2 算法思路:

64.3 代码演示:

64.4 总结反思

65 力扣946 验证栈序列

65.1 题目解析:

65.2 算法思路:

65.3 代码演示:

65.4 总结反思


61 力扣 1042 删除字符串中的所有相邻重复项

61.1 题目解析:

这个题目的本意其实跟那个消消乐游戏比较像。就是两个相同的直接消除。并且,从这道题开始一直到咱们今天的博客结束,使用的都是栈这个算法。

61.2 算法思路:

61.3 代码演示:

//删除字符串中的所有相邻重复项
string removeDuplicates(string s) {string ret;//使用数组来模拟栈结构for (auto& ch : s){if (ret.size() && ret.back() == ch) ret.pop_back();//前提是这个ret里面得有元素,才可以进行ret.back()==ch的这判断else ret += ch;}return ret;
}
int main()
{string s("abbaca");cout << removeDuplicates(s) << endl;return 0;
}

61.4 总结反思

理解这个题目的解法,咱们下一道题目还得用到这个解法。

62. 力扣844 比较含退格的字符串

62.1 题目解析:

这道题目也很好理解。就是遇到#的话,直接将栈顶元素弹出即可

62.2 算法思路:

这道题目的解法我可以说与上一道题几乎一样的,待会大家看代码就知道了。不过这道题目需要处理一下边界情况。并且这道题目的边界情况只有一种。待会代码分析

62.3 代码演示:

//比较含退格的字符串
bool backspaceCompare(string s, string t) {string ret1;for (auto& ch : s){if (ret1.size() && ch == '#') ret1.pop_back();else if (ret1.size() == 0 && ch == '#'){;}else ret1 += ch;}string ret2;for (auto& x : t){if (ret2.size() && x == '#') ret2.pop_back();else if (ret2.size() == 0 && x == '#'){;}else ret2 += x;}return ret1 == ret2;
}
int main()
{string s("y#fo##f");string t("y#f#o##f");cout << backspaceCompare(s, t) << endl;return 0;
}

那么这道题目需要处理的边界情况就是s:"y#fo##f".t:"y#f#o##f".

那么这种情况就需要加上栈为空,并且此时的字符是#,这种情况,否则就会导致返回的结果是错误的。

62.4 总结反思

这道题目很是巧妙地运用了上一题的解法,大家可以仔细的研读一下

63 力扣227 基本计算器

63.1 题目解析:

这道题目可以说也是有点难度的,边界情况很多。所以下面要仔细的听我讲解这道题目。

63.2 算法思路:

一般表达式求值类的题目,就是利用栈来模拟计算过程。并且,用数组模拟栈。

且,这道题目需要用到双栈,一个栈来维护nums,另外一个栈用来维护,符号op

咱们先来看一下模拟的过程:

OK,再来总结一下:

63.3 代码演示:

//基本计算器II
int calculate(string s) {vector<int>  ret;//用数组来模拟栈结构int i = 0;int n = s.size();char op = '+';//初始化为加法符号while (i < n){if (s[i] == ' ') i++;//如果说这个位置为空格,那么直接跳过这个位置即可else if (s[i] >= '0' && s[i] <= '9')//这个i此时的位置是1到9之间的数字{int tmp = 0;//tmp来存储数字while (i < n && s[i] >= '0' && s[i] <= '9')//确保不越界,并且最基本的i这个位置还必须得是数字才可以{tmp = tmp * 10 + (s[i] - '0');//字符转为数字i++;}if (op == '+') ret.push_back(tmp);else if (op == '-') ret.push_back(-tmp);else if (op == '*') ret.back() *= tmp;//这个vector数组的最后一个元素,用.back()来表示else ret.back() /= tmp;//最后不需要再i++了,因为上面已经加加过了,此时的这里就是乘除号的位置了(如果后面不是数字的话)}else {op = s[i];//更新一下操作符,这个可不是再往ret这个栈里面加了,双栈i++;}}int outcome = 0;for (auto& e : ret){outcome += e;//此时,这个ret中已经全部是数字了,不是字符了,因为上面已经转换过了}return outcome;
}
int main()
{string s(" 3+5 / 2 ");cout << calculate(s) << endl;return 0;
}

63.4 总结反思

这道题目,就是基本计算器II还是比较简单的,那个计算器I才是真的难,那个还得掌握逆波兰表达式等等的知识。等有时间出个专题再讲讲吧

64 力扣394 字符串解码

64.1 题目解析:

大家看这个图是不是就清楚多了呢。并且,咱们需要涉及到细节的处理。有的是整体的处理或者是分类讨论。不过本题使用的是分类讨论这些边界情况

64.2 算法思路:

咱们先来模拟一下:

最后再总结一下这个讨论情况:

64.3 代码演示:

//字符串解码
string decodeString(string s) {stack<int> nums;stack<string> ret;ret.push("");//先放入一个空的字符串,防止访问越界int i = 0; int n = s.size();while (i < n)//从头开始遍历{if (s[i] >= '0' && s[i] <= '9'){int tmp = 0;while (i < n && s[i] >= '0' && s[i] <= '9'){tmp = tmp * 10 + s[i] - '0';i++;}nums.push(tmp);//将tmp放到数字栈中}else if (s[i] == '['){i++;//先跳过这个左括号,string tmp;while (i < n && s[i] >= 'a' && s[i] <= 'z'){tmp += s[i];i++;}ret.push(tmp);//将这个tmp放到字符串栈中去}else if (s[i] == ']'){string tmp = ret.top();ret.pop();//别忘了删除这个栈顶的元素int kk = nums.top();nums.pop();while (kk--){ret.top() += tmp;}i++;//跳过这个右括号}else{string tmp;while (i < n && s[i] >= 'a' && s[i] <= 'z')//这个的i<n是必须得加的,因为若最后两个是de这个字符串的话,不加i<n,就越界访问了{tmp += s[i];i++;}ret.top() += tmp;;//将这个tmp放到字符串栈的栈顶元素的后面去中去}}return ret.top();//注意是返回栈顶元素。不可以返回ret。因为返回类型与返回值不匹配
}
int main()
{string s("2[abc]3[cd]ef");cout << decodeString(s) << endl;return 0;
}

64.4 总结反思

本题也是用到了相当多的知识,不过最重要的莫过于这个栈

65 力扣946 验证栈序列

65.1 题目解析:

这个问题,我依稀记得,我在牛客网上面也做过,但是当时我可没有这么清晰的思路。不过今天,我可以以一种很好的思维讲解出来。

65.2 算法思路:

65.3 代码演示:

//验证栈序列
bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {stack<int> ret;int i = 0; int n = pushed.size();int j = 0;while (j < n)//这里你如果说要写while的话,不能使用i<n,因为你的i遍历的主要是popped,而这个是入栈的元素,应该再定义一个指针去遍历pushed这个数组。或者直接使用范围for也可以{ret.push(pushed[j]);while (ret.size() && ret.top() == popped[i])//栈不能为空,并且,栈顶元素正好等于popped数组的i位置的元素{ret.pop();i++;//出栈后,判断是否还继续相等,若还继续相等,则继续出栈}j++;}return ret.empty();//判断i是否越界了即可。或者是判断栈是否为空都可以//return n==i;
}
int main()
{vector<int> pushed = { 1,2,3,4,5 };vector<int> popped = { 4,5,3,2,1 };cout << validateStackSequences(pushed, popped) << endl;return 0;
}

65.4 总结反思

那么咱们今天的题目就讲解完了。关于栈这方面的,题目博主总结的并不是很完整。大家可以补充

本篇完...................

http://www.lryc.cn/news/611099.html

相关文章:

  • 关于如何SecureCRT软件连接开发板后默认显示大字体,且重启开发板或重新连接时不会重置的方法
  • Android原生项目集成Flutter模块极简指南
  • Linux学习-数据结构(链表)
  • 深入浅出:Ajax 与 Servlet 实现前后端数据交互
  • 01-数据结构
  • ES(Elasticsearch)进程掉线(节点脱离集群)问题
  • 18-Chapter03-Example05
  • Ubuntu24.04环境下非DOCKER方式安装Mysql5.7
  • 《Linux编译器:gcc/g++食用指南》
  • Go 单元测试:如何只运行某个测试函数(精确控制)
  • 龙芯(loongson) ls2k1000 openwrt
  • 007TG洞察:高效运营Telegram私域流量:技术挑战与自动化解决方案探索
  • Wisdom SSH:自动化网络配置管理的领航者
  • LangChain入门:内存、记录聊天历史 ChatMessageHistory、模型、提示 ( Prompt )、模式 ( Schema )
  • golang的切片
  • 2025年特种设备作业人员考试题库及答案(流动式起重机Q2)
  • MyBatisPlus查询数据库中所有表的数据(AI)
  • GPU 基础矩阵精规组织教程:从基础作用到实战应用
  • Redis里面什么是sdshdr,可以详细介绍一下吗?
  • 用 Spark 找出最大值:高性能计算的正确姿势
  • 8XC552 系列单片机的定时器 T2 和捕捉比较逻辑是什么
  • 如何通过视觉+自动化组合拳提升UI测试的质量
  • Centos-Stream 10 安装教程(2025版图文教程)
  • Vue2博客项目笔记(第一天)
  • SpringBoot集成STOMP
  • CS231n Lecture11 目标检测和图像分割笔记
  • mq_timedsend系统调用及示例
  • 浮动路由和BFD配置
  • 智能体架构与风险全景:从LLM工作流到OWASP Top 10安全浅谈
  • 本地使用uv管理的python项目怎么部署到服务器?