当前位置: 首页 > 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.xdnf.cn/news/1247167.html

相关文章:

  • Rust进阶-part3-生命周期
  • Docker Desktop
  • K8s Master状态NotReady
  • 组织架构与软件架构协同演进实践指南
  • 网络 —— 笔记本(主机)、主机虚拟机(Windows、Ubuntu)、手机(笔记本热点),三者进行相互ping通
  • Redis面试精讲 Day 11:Redis主从复制原理与实践
  • 微服务—Gateway
  • Solidity智能合约基础
  • python学智能算法(三十三)|SVM-构建软边界拉格朗日方程
  • 《零基础入门AI:传统机器学习进阶(从拟合概念到K-Means算法)》
  • 机器学习——集成学习(Ensemble Learning)详解:原理、方法与实战应用
  • 机器学习 集成学习之随机森林
  • python开发环境安装多系统完整版
  • 工作相关: 预刷真值与人工标注的真值之间的关系 以及 真值与原始数据的关系,
  • Vue3 defineAsyncComponent() 函数
  • 【Unity笔记】Unity TextMeshPro 字体显示为方块的终极解决方案(含中文、特殊字符支持)
  • android直连SQLserver的可行性分析
  • TCP协议与UDP协议
  • 智慧能源场景设备缺陷漏检率↓76%:陌讯多模态融合检测方案实战解析
  • Redis备份方案:持久化与外部工具全解析
  • JVM(Java Virtual Machine,Java 虚拟机)超详细总结
  • Spring之【详解FactoryBean】
  • C++ 网络编程入门:TCP 协议下的简易计算器项目
  • 数据结构04 栈和队列
  • 工业级 CAN 与以太网桥梁:串口服务器CAN通讯转换器深度解析(下)
  • Dot1x认证原理详解
  • ChatGPT以及ChatGPT强化学习步骤
  • 数据结构(三)双向链表
  • VSCode中使用Qt
  • 7、Redis队列Stream和单线程及多线程模型