【C++ 算法进阶】算法提升八
复杂计算 (括号问题相关递归套路 重要)
题目
给定一个字符串str str表示一个公式 公式里面可能有整数 + - * / 符号以及左右括号 返回最终计算的结果
题目分析
本题的难点主要在于可能会有很多的括号 而我们直接模拟现实中的算法的话code会难写 要考虑的情况很多
那么我们首先写出加入没有括号应该怎么计算呢
我们这里只需要首先计算乘法和除法 再计算加法和减法
代码
int process(string& s1) {// s1 表示计算的公式stack<string> st;int cur = 0;for (int i = 0; i < s1.size(); i++) {if (s1[i] < '0' || s1[i] > '9'){if (!st.empty()) {string test = st.top();if (test == "*" || test == "/") {string op = st.top();st.pop();int left = stoi(st.top());st.pop();int right = cur;if (op == "*") {cur = left * right;}else{cur = left / right;}}}st.push(to_string(cur));string ops = string(1, s1[i]);st.push(ops);cur = 0;}else{cur = cur * 10 + (s1[i] - '0');}}string test = st.top();if (test == "*" || test == "/") {string op = st.top();st.pop();int left = stoi(st.top());st.pop();int right = cur;if (op == "*") {cur = left * right;}else{cur = left / right;}}st.push(to_string(cur));stack<string> st2;while (!st.empty()){st2.push(st.top());st.pop();}// 最后我们按照顺序计算栈里面的结果while (st2.size() != 1){int left = stoi(st2.top());st2.pop();string op = st2.top();st2.pop();int right = stoi(st2.top());st2.pop();if (op == "+") {st2.push(to_string(left + right));}else{st2.push(to_string(left - right));}}return stoi(st2.top());
}
如果遇到括号怎么办呢

比如说我们现在计算到* 之后 遇到了一个 (
此时我们不进行继续的计算 而是使用递归 将这个括号里的内容传递给下个函数进行计算 我们只需要知道返回值即可
当然只知道返回值是不够的 因为我们还需要知道递归函数返回之后需要从哪一个位置开始计算
所以说递归函数的返回值要返回一个数组 数组里面存储着括号内计算的数值以及指针走到的位置
vector<int> process(string& s1 , int n ) {// s1代表字符串int i = n;int cur = 0;stack<string> st;while (i < s1.size() && s1[i] != ')'){if ((s1[i] < '0' || s1[i] > '9' ) && s1[i] != '('){if (!st.empty()) {string test = st.top();if (test == "*" || test == "/") {string op = st.top();st.pop();int left = stoi(st.top());st.pop();int right = cur;if (op == "*") {cur = left * right;}else{cur = left / right;}}}st.push(to_string(cur));string ops = string(1, s1[i]);st.push(ops);cur = 0;i++;}else if (s1[i] >= '0' && s1[i] <= '9'){cur = cur * 10 + (s1[i] - '0');i++;}else{vector<int> ans = process(s1 , i + 1);i = ans[1];cur = ans[0];}}// 走到这里说明碰到了边界了string test = st.top();if (test == "*" || test == "/") {string op = st.top();st.pop();int left = stoi(st.top());st.pop();int right = cur;if (op == "*") {cur = left * right;}else{cur = left / right;}}st.push(to_string(cur));stack<string> st2;while (!st.empty()){st2.push(st.top());st.pop();}// 最后我们按照顺序计算栈里面的结果while (st2.size() != 1){int left = stoi(st2.top());st2.pop();string op = st2.top();st2.pop();int right = stoi(st2.top());st2.pop();if (op == "+") {st2.push(to_string(left + right));}else{st2.push(to_string(left - right));}}return { stoi(st2.top()), i + 1 };
}
我们只需要在遇到左括号的时候将计算的任务丢给递归函数 也就是调用下面这段代码
else{vector<int> ans = process(s1 , i + 1);i = ans[1];cur = ans[0];}
即可
装最多水的容器 (贪心)
题目
本题为LC原题 题目如下

题目分析
装水的容积由两个部分决定
- 两块板子之间的宽度
- 两块板子中较小的那块板子的高度
所以说 只要我们找出每个宽度的最大值 最后对比一下 我们就能得出最终答案
所以说我们一开始自然是用最左和最右边的板子装水
之后宽度-- 那么我们要想得到最大值是不是要在高度上花心思
我们肯定要舍弃掉较为短的一块板子
之后用代码实现上述内容即可
代码
class Solution {
public:int maxArea(vector<int>& height) {int left = 0;int right = height.size() - 1;int ans = 0;while (left < right) {int h = min(height[left] , height[right]);int w = right - left;ans = max(w * h , ans);if (height[left] < height[right]) {left++;}else {right--;}}return ans;}
};
蛇走格子问题 (动态规划)
题目
假设现在有一个二维数组 每个位置存放着一个整数 (可以为负)
现在有一条蛇要从这个数组的最左边开始找出一条整数相加为最大值的路径
蛇只能往右上 右 右下走
如果叠加到负数则蛇立刻死亡(之前成绩归为-1)
蛇有一种能力 只能发动一次 可以让格子的值变成相反数
题目分析
这是一道经典的动态规划问题 我们可以设计一个如下的函数
// 数组arr上返回i j位置的info信息
// info信息 使用了能力和没有使用能力返回的最大值
info process(vector<vector<int>>& arr, int i, int j) {
}
之后只要跟着递归三部走
- 找终止条件
- 找可能性
- 返回最终结果
即可
终止条件为 当J == 0的时候 我们只有此时用不用能力这两种选择
可能性就有很多了 总体可以分为两类
- 没用能力
- 用了能力
当然 用了能力还要区分 是不是这次用的
之后如果前面的结果有-1 我们则要将其排除出可能性(即答案设置为-1)
代码
// 数组arr上返回i j位置的info信息
// info信息 使用了能力和没有使用能力返回的最大值
info* process(vector<vector<int>>& arr, int i, int j) {if (j == 0){// 不使用能力 -1表示可能达到int no = arr[i][j] >= 0 ? arr[i][j] : -1;int yes = -arr[i][j] >= 0 ? -arr[i][j] : -1;return new info(no, yes);}// 真正的可能性// 首先肯定有左边int preno = -1;int preyes = -1;auto info1 = process(arr, i, j);preno = max(info1->_no, preno);preyes = max(info1->_yes, preyes);if (i > 0){auto info1 = process(arr, i - 1, j - 1);preno = max(info1->_no, preno);preyes = max(info1->_yes, preyes);}if (i < arr.size() - 1){auto info1 = process(arr, i + 1, j - 1);preno = max(info1->_no, preno);preyes = max(info1->_yes, preyes);}// 列可能性int p1 = preno + arr[i][j];if (p1 < 0){p1 = -1;}if (preno = -1){p1 = -1;}int p2 = preyes + arr[i][j];int p3 = preno - arr[i][j];p2 = max(p2, p3);if (p2 < 0){p2 = -1;}if (preyes = -1){p2 = -1;}if (preno = -1){p3 = -1;}return new info(p1, p2);
}int _process(vector<vector<int>>& arr) {int ans = 0;for (int i = 0; i < arr.size(); i++) {for (int j = 0; j < arr[0].size(); j++){auto res = process(arr, i, j);ans = max(ans, max(res->_no, res->_yes));}}return ans;
}
路径问题 (动态规划)
题目
给定你一个二维数组 二维数组中存放着a~z的二十六个字符 再给你一个字符串str
现在请问 从这个二维数组中的任意一个位置开始找 是否能找到一条路径能组成字符串str
- 如果路径可以重复是否可以组成
- 如果路径不能重复是否可以组成
题目分析
凡是动态规划的题目我们首先来想思路 因为题目中是一个二维数组 所以我们肯定要使用两个变量来标识唯一一个位置
此外对于字符串str 我们也需要一个变量来确定位置
// 这个函数的意义是从i j位置开始 arr中的字符能不能组成包括str[K]位置及其往后所有位置
bool process(vector<vector<char>>& arr, int i, int j, int k) {
}
我们验证当前字符是否符合之后 只需要调用递归函数查看下一个函数是否符合即可
// 这个函数的意义是从i j位置开始 arr中的字符能不能组成包括str[K]位置及其往后所有位置
bool process(vector<vector<char>>& arr, string& str,int i, int j, int k) {if (k == str.size()){return true;}if (i < 0 || i > arr.size() - 1 || j < 0 || j > arr[0].size() - 1 || arr[i][j] != str[k]){return false;}bool ans = false;// 可能性 走到这里说明前面都符合if (process(arr, str, i + 1, j + 1, k + 1) || process(arr, str, i + 1, j - 1, k + 1) || process(arr, str, i - 1, j + 1, k + 1)|| process(arr, str, i - 1, j - 1, k + 1)){ans = true;}return ans;
}
如果不允许路径重复呢?
这个问题的难点实际在于我们如何标记之前走过的路径
这里推荐使用回溯法
我们每次走过一个路径的之后将当前格子标0
之后验证完毕之后再将格子改回去就行
bool process(vector<vector<char>>& arr, string& str,int i, int j, int k) {if (k == str.size()){return true;}if (i < 0 || i > arr.size() - 1 || j < 0 || j > arr[0].size() - 1 || arr[i][j] != str[k]){return false;}arr[i][j] = 0;bool ans = false;// 可能性 走到这里说明前面都符合if (process(arr, str, i + 1, j + 1, k + 1) || process(arr, str, i + 1, j - 1, k + 1) || process(arr, str, i - 1, j + 1, k + 1)|| process(arr, str, i - 1, j - 1, k + 1)){ans = true;}arr[i][j] = str[k];return ans;
}
相关文章:
【C++ 算法进阶】算法提升八
复杂计算 (括号问题相关递归套路 重要) 题目 给定一个字符串str str表示一个公式 公式里面可能有整数 - * / 符号以及左右括号 返回最终计算的结果 题目分析 本题的难点主要在于可能会有很多的括号 而我们直接模拟现实中的算法的话code会难写 要考虑…...
阿里云实时数据仓库HologresFlink
1. 实时数仓Hologres特点 专注实时场景:数据实时写入、实时更新,写入即可见,与Flink原生集成,支持高吞吐、低延时、有模型的实时数仓开发,满足业务洞察实时性需求。 亚秒级交互式分析:支持海量数据亚秒级交…...
生成式语言模型的文本生成评价指标(从传统的基于统计到现在的基于语义)
文本生成评价指标 以 BLEU 为代表的基于统计的文本评价指标基于 BERT 等预训练模型的文本评价指标 1.以 BLEU 为代表的基于统计的文本评价指标 1.BLEU(Bilingual Evaluation Understudy, 双语评估辅助工具) 所有评价指标的鼻祖,核心思想是比较 候选译文 和 参考…...
【网安案例学习】暴力破解攻击(Brute Force Attack)
### 案例与影响 暴力破解攻击在历史上曾导致多次重大安全事件,特别是在用户数据泄露和账户被盗的案例中。随着计算能力的提升和密码管理技术的进步,暴力破解的威胁虽然有所减弱,但仍需警惕,特别是在面对高价值目标时。 【故事一…...
时间序列预测(十八)——实现配置管理和扩展命令行参数解析器
如图,这是一个main,py文件,在此代码中,最开始定义了许多模型参数,为了使项目更加灵活和可扩展,便于根据不同的需求调整参数和配置,可以根据实际需要扩展参数和配置项。 下面是如何实现配置管理和扩展命令行…...
Vue问题汇总解决
作者:fyupeng 技术专栏:☞ https://github.com/fyupeng 项目地址:☞ https://github.com/fyupeng/distributed-blog-system-api 留给读者 我们经常在使用Vue开发遇到一些棘手的问题,解决后通常要进行总结,避免下次重复…...
Spark学习
Spark简介 1.Spark是什么 首先spark是一个计算引擎,而不是存储工具,计算引擎有很多: 第一代:MapReduce廉价机器实现分布式大数据处理 第二代:Tez基于MR优化了DAG,性能比MR快一些 第三代:Spark…...
一些小细节代码笔记汇总
Python cv2抓取摄像头图片保存到本地 import cv2 import datetime, ossavePath "E:/Image/"if not os.path.exists(savePath):os.makedirs(savePath)cap cv2.VideoCapture(0) capture Falseif not cap.isOpened():print("无法打开摄像头")exit()while…...
L4.【LeetCode笔记】链表题的VS平台调试代码
不用调用87.【C语言】数据结构之链表的头插和尾插文章提到的头插函数 记下这个模板代码,可用于在Visual Studio上调试出问题的测试用例 如创建链表[1,2,3,4,5] #include <stdilb.h> // Definition for singly-linked list.struct ListNode {int val;struct ListNode *…...
JavaCV 之高斯滤波:图像降噪与细节保留的魔法
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c=1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编程,高并发设计,Springboot和微服务,熟悉Linux,ESXI虚拟化以及云原生Docker和K8s…...
VsCode显示空格
ctrl shift p选择Preferences: Open User Settings (JSON) 加上"editor.renderWhitespace": "all" {"cmake.configureOnOpen": true,"files.encoding": "gb2312","editor.fontVariations": false,"edito…...
.Net C# 基于EFCore的DBFirst和CodeFirst
DBFirst和CodeFirst 1 概念介绍 1.1 DBFirst(数据库优先) 含义:这种模式是先创建数据库架构,包括表、视图、存储过程等数据库对象。然后通过实体框架(Entity Framework)等工具,根据已有的数据…...
w012基于springboot的社区团购系统设计
🙊作者简介:拥有多年开发工作经验,分享技术代码帮助学生学习,独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。🌹赠送计算机毕业设计600个选题excel文件,帮助大学选题。赠送开题报告模板ÿ…...
笔记本降频超鬼锁屏0.39电脑卡到不行解决办法实操记录
1、最开始没发现cpu问题,我发现我电脑突然异常的卡顿,最开始我怀疑是不是微软win用久了或者自动更新导致的问题,于是自己重装了操作系统 发现问题依然存在 2、我怀疑难道我的 cpu 内存 固态硬盘 其中一个有点问题?心想要是硬盘的…...
优选算法第四讲:前缀和模块
优选算法第四讲:前缀和模块 1.[模板]前缀和2.【模板】二维前缀和3.寻找数组的中心下标4.除自身以外数组的乘积5.和为k的子数组6.和可被k整除的子数组7.连续数组8.矩阵区域和 1.[模板]前缀和 链接: link #include <iostream> #include <vector> using…...
ubuntu20.04 加固方案-设置限制su命令用户组
一、编辑/etc/pam.d/su配置文件 打开终端。 使用文本编辑器(如vim)编辑/etc/pam.d/su文件。 vim /etc/pam.d/su 二、添加配置参数 在打开的配置文件的中,添加以下参数: auth required pam_wheel.so 创建 wheel 组 并添加用户 …...
TDengine数据备份与恢复
TDengine数据备份与恢复 一、数据备份和恢复介绍二、基于 taosdump 进行数据备份恢复三、基于 taosExplorer 进行数据备份恢复3.1 taosExplorer 的安装与配置3.2 使用taosExplorer 进行数据备份 一、数据备份和恢复介绍 官网地址:TDengine - 数据备份和恢复 为了防止…...
2024最新的开源博客系统:vue3.x+SpringBoot 3.x 前后端分离
本文转载自:https://fangcaicoding.cn/article/54 大家好!我是方才,目前是8人后端研发团队的负责人,拥有6年后端经验&3年团队管理经验,截止目前面试过近200位候选人,主导过单表上10亿、累计上100亿数据…...
研究中的“异质性”、“异质性结果”是指?
“异质性”这个词在统计学和研究中指的是数据、现象或群体之间的差异,即不同个体、组别、区域或时间点的表现或特征并不相同。相对的概念是“同质性”,即所有个体或组别在某一方面表现相同或接近。 异质性(Heterogeneity)的含义 …...
Springboot整合AOP和redis
aop pom.xml <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId> </dependency> 开启自动代理 注意:在完成了引入AOP依赖包后,一般来说并不需要去做其他…...
C++_核心编程_多态案例二-制作饮品
#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...
视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...
C# 表达式和运算符(求值顺序)
求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如,已知表达式3*52,依照子表达式的求值顺序,有两种可能的结果,如图9-3所示。 如果乘法先执行,结果是17。如果5…...
android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...
FFmpeg avformat_open_input函数分析
函数内部的总体流程如下: avformat_open_input 精简后的代码如下: int avformat_open_input(AVFormatContext **ps, const char *filename,ff_const59 AVInputFormat *fmt, AVDictionary **options) {AVFormatContext *s *ps;int i, ret 0;AVDictio…...
es6+和css3新增的特性有哪些
一:ECMAScript 新特性(ES6) ES6 (2015) - 革命性更新 1,记住的方法,从一个方法里面用到了哪些技术 1,let /const块级作用域声明2,**默认参数**:函数参数可以设置默认值。3&#x…...
