中缀表达式求值问题

2023-10-27

1)有无括号

2)一种优先级运算符(只有+-或*/) 还是2种(+- 和*/都有)

3) 求逆波兰序列,求值,求表达式树


两种思路

1.分治 (求值,和求表达式树都可以用)nlogn

1)先去掉冗余括号(两边最外面的,如(1), (1 + 2) ),如果有的话。找到优先级最小的运算符的位置p,如果不存在,说明是一个数字,返回atoi后的值

2)两边递归求值 

3)对两边的值应用该运算符,返回结果。

对于找最小运算符:在括号内的不考虑,因为其优先级更高,同一优先级的运算符,前面的优先级高,后面的低。

map<char, function<int(int, int)>> = {{'+', [](int a, int b) {return a + b;}}, {'-', [](int a, int b) {return a - b;}}};

int eval(string &s, int l, int r) {
    for (; l < r && s[l] == '( && s[r] == ')'; ++l, --r ) ;
    int p = findLowestOp(s, l, r);
    if (p == -1) return stoi(s.substr(l, r - l + 1));
    return op[s[p]](eval(s, l, p - 1), eval(s, p + 1, r));
}

int findLowestOp(string &s, int l, int r) {
    int p = -1 , nestedLevel = 0;
    for (int i = l; i <= r; ++i) {
        if (s[i] == '(') ++nestedLevel;
        else if (s[i] == ')') --nestedLevel;
        else if (string("+-*/").find(s[i]) != string ::npos && nestedLevel == 0 && (p < 0 || s[i] == '+' || s[i] == '-' || s[p] == '*' || s[p] == '/' )) p = i;
    }
    return p;
}

2 利用单调栈 O(n)

算法主要参与者:

1)操作符函数映射表

2)操作数栈operand,操作符栈op

3)token stream (可以先用操作符split,也可以实时tokenize)


算法框架:token 流加一个结束符#,依次取token:

1)如果token是操作数,atoi, 入operand栈

2)token是操作符,while token优先级比op栈顶元素低,则取op栈顶操作符做运算,相应的操作数是operand栈的最近的两个数

对于括号,可以看作是一种分界,左括号可以看作是一个新的op栈的栈底, 右括号可以看作是括号内表达式的结束符。

def evaluateExpression(self, expression):
	m = {'+' : lambda a, b : a + b, '-' : lambda a, b : a - b, '*' : lambda a, b : a * b, '/' : lambda a, b : a / b}
	op, oprand = [], []
	for token in expression + ['#']:
		if token.isdigit(): oprand.append(int(token))
		else:
			while len(op) > 0 and token != '(' and op[-1] != '(' and  (token in '#)+-' or op[-1] in '*/'):
				b = oprand.pop();
				oprand[-1] = m[op.pop()](oprand[-1], b)
			if token == ')': op.pop()
			else: op.append(token)
	if len(oprand) > 0: return oprand[-1]
	return 0


详细解释条件判断部分:

len(op) > 0 和 op[-1]!= '(' 都是判断当前栈不为空(左括号mark一个新op栈的开始)

token != '(' 表示这不是一个“复合操作数”,括号代表一个子表达式,是值,这里比较的是运算符。

token in '#)+=' 当前运算符是这些,肯定不如栈顶运算符优先级高

op[-1] in '*/'  栈顶上已经是最高优先级的


一个逆向问题,给定一组数A,添加操作符使得表达式值为给定target

t是表达式最后一个term,

def solve(A, i, v, t, target, e):
    if i == len(A):
        if v == target: print e
    else:
        if i == 0: solve(A, i + 1, A[i], A[i], target, str(A[i]))
        else:
            solve(A, i + 1, v + A[i], A[i], target, e + '+' + str(A[i]))
            solve(A, i + 1, v - A[i], -A[i], target, e + '-' + str(A[i]))
            solve(A, i + 1, v - t + t * A[i], f * A[i], target, e + '*' + str(A[i]))
            if A[i] != 0: solve(A, i + 1, v - t + t / A[i], f / A[i], target, e + '/' + str(A[i]))



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

中缀表达式求值问题 的相关文章

  • 运行时检查失败 #2 - 变量“x”周围的堆栈已损坏

    在以下代码中返回时 我收到此运行时检查失败 我相信类似的代码在程序的其他地方运行良好 有任何想法吗 String GetVariableName CString symbol CString filepath char acLine 512
  • Linux 内核如何强制堆栈大小限制?

    我知道堆栈大小可以通过限制工具进行控制 但是内核如何强制执行其中一些限制 例如 RLIMIT STACK 由于linux不涉及堆栈操作 只是mov或push指令 那么当超出限制时内核如何发出SIGSEGV 据我了解 对于虚拟寻址 CPU 提
  • 如何用一个数组实现3个栈?

    有时 我会遇到以下面试问题 如何用一个数组实现3个堆栈 当然 任何静态分配都不是解决方案 空间 而非时间 高效 你可以 1 定义两个堆栈 从数组端点开始并沿相反方向增长 2 将第三个堆栈定义为从中间开始并向您想要的任何方向增长 3 重新定义
  • ARM GCC 生成函数序言

    我提到 ARM 工具链可以生成不同的函数序言 实际上 我看到两个 obj 文件 vmlinux 具有完全不同的函数序言 第一种情况如下所示 push some registers maybe fp lr lr ommited in leaf
  • C++:在堆栈中存储结构

    我有一个结构 struct Vehicle char ad Arrival departure char string license license value int arrival arrival in military time 我
  • 左结合性仅适用于 Postfix 表达式吗?

    在计算后缀表达式时 关联性是否总是从左到右 如果是 为什么 如果没有 为什么 None
  • 有意的缓冲区溢出并不总是导致程序崩溃

    考虑以下最小 C 程序 案例编号1 include
  • C# 中静态结构存储在哪里?

    From 这个问题 https stackoverflow com questions 2565331 fields of class are they stored in the stack or heap我明白 结构可以在堆栈或寄存器中
  • 如何在 Kotlin 中使用堆栈?

    如何在 Kotlin 中使用 Stack 来自 java 或者还有其他替代方案吗 我正在尝试将列表转换为堆栈 科特林 1 3 70介绍了kotlin collections ArrayDeque https kotlinlang org a
  • geom_text 仅位于堆积条形图的顶部

    我想仅在堆叠条形图的顶部添加标签 这是我的数据框 create data frame building lt c Burj nKhalifa Zifeng nTower Bank of nAmerica Tower Burj Al Arab
  • 使用callstack在C中实现堆栈数据结构?

    我对 C 下内存结构的理解是 程序的内存与堆栈和堆分开 每个堆栈和堆都从块的两端生长 可以想象分配所有 RAM 但显然抽象为某种操作系统内存片段管理器 堆栈设计用于处理局部变量 自动存储 堆设计用于内存分配 动态存储 编者注 有一些 C 实
  • 从 Android 应用程序堆栈中手动删除活动

    我一直在开发 Android Native App 我想做的是 Activities A gt B gt C Then A gt B gt C gt C 从 C Activity 中 如果它再次指向 C 那么我想手动从堆栈中删除 C B 在
  • 使用 Stacks Java 将中缀转换为 Postfix

    我正在尝试编写一个程序将中缀表达式转换为后缀表达式 我正在使用的算法如下 1 Create a stack 2 For each character t in the expression If t is an operand append
  • std::stack 是否公开迭代器?

    是否std stack在 C STL 中公开底层容器的任何迭代器 还是应该直接使用该容器 根据堆栈的定义 堆栈没有迭代器 如果您需要带有迭代器的堆栈 则需要自己在其他容器 std list std vector 等 之上实现它 堆栈文档在这
  • 如何在 R 中堆叠数据框[重复]

    这个问题在这里已经有答案了 我有一个数据框 我想将其堆叠在 R 中 这样我最终会得到三列 下面是当前格式的一些示例数据 gt dput df structure list Day c d1 d2 d3 d4 d5 d6 d7 d8 d9 d
  • 使用javascript对堆栈元素进行排序

    我试图理解使用递归对堆栈元素进行排序http www geeksforgeeks org sort a stack using recursion http www geeksforgeeks org sort a stack using
  • C 函数堆栈布局

    我有一个看起来像这样的函数 int bof char str char buffer 12 strcpy buffer str return 1 我正在尝试覆盖其返回地址 我发现我可以通过使用来做到这一点 例如 memcpy buffer
  • C - '=' 标记之前的预期表达式...在没有 '=' 的行上

    我疯狂地试图找出这个与现实 我的代码没有明显联系的错误消息 我一直在这里搜索并得出一个结论 你会讨厌 typedef 隐藏的指针 抱歉 这超出了我的控制范围 教授以这种方式提供了代码 我正在编辑问题中指定的代码 我弹出完整节点以避免每个推送
  • 每个进程是否都存在内核堆栈?

    每个用户空间进程是否都存在一个内核堆栈和一个用户空间堆栈 如果两个堆栈都存在 那么每个用户空间进程应该有 2 个堆栈指针 对吗 在 Linux 中 每个任务 用户空间或内核线程 都有一个 8kb 或 4kb 的内核堆栈 具体取决于内核配置
  • Android 堆栈大小

    我如何获取和更改 Android 应用程序的堆栈大小 即使是主线程 主线程堆栈大小是在固件中设置的 无法修改 除非修改您自己手机的固件 正如斯特朗先生指出的那样 对于您分叉的线程 您可以设置自己的堆栈大小

随机推荐

  • 【C++拾遗之八】#pragmaonce与#ifndef的用法总结

    宏定义 一 两种宏定义的功能 二 两种宏定义的用法 三 两种宏定义的区别 一 两种宏定义的功能 ifndef 和 pragma once都是C C 中的两种宏定义 它们的作用是为了避免同一个头文件被多次包含 include note 只能保
  • Nginx入门笔记

    目录 Nginx 快速入门 1 启动 停止和重新加载 Nginx 配置 2 配置文件的结构 3 提供静态内容服务 静态网站 4 设置简单的代理服务器 5 设置 FastCGI 代理 Nginx 进程和运行时控制 1 主进程和工作进程 2 控
  • idea 配置(下载) golang 环境 GOROOT、GOPATH

    windows 10 平台 golang镜像下载地址 https gomirrors org 选择稳定版的windows amd64 msi或者zip zip 解压到目录即可 msi 打开直接安装 配置环境变量 高版本有的会自己配置环境变量
  • [定向爬虫] 网络爬虫实例2-淘宝定向爬虫

    import requests import re import time 获取html页面 def getHTMLText url try r requests get url timeout 30 r raise for status
  • 【雕爷学编程】MicroPython手册之 WiPy 特定端口库 wipy.machine.I2C.stop()

    MicroPython是为了在嵌入式系统中运行Python 3编程语言而设计的轻量级版本解释器 与常规Python相比 MicroPython解释器体积小 仅100KB左右 通过编译成二进制Executable文件运行 执行效率较高 它使用
  • 一文了解电商大促系统的高可用保障思路

    本文面向受众可以是运营 可以是产品 也可以是研发 测试人员 作者希望通过如下思路 知历史 gt 清家底 gt 明目标 gt 定战略 gt 做战术 gt 促成长 帮助大家能够了解电商大促系统的高可用保障 减少哪些高深莫测的黑话和高大尚的论调
  • 【linux】linux中fork()详解(实例讲解)

    目录 linux中fork 函数详解 从一道面试题谈linux下fork的运行机制 linux中fork 函数详解 原文 linux中fork 函数详解 原创 实例讲解 jason314的博客 CSDN博客 fork 函数 一 fork入门
  • Conda 创建和删除虚拟环境

    1 检验当前conda的版本 conda V 2 conda常用的命令 查看已有的虚拟环境 conda env list 创建虚拟环境和删除虚拟环境 anaconda命令创建python版本为x x 名字为env name的虚拟环境 env
  • 微信小程序授权获取头像昵称的最新形式——头像昵称填写

    微信小程序授权用户信息 不知道有没有人像我一样 从wx getUserInfo到wx getUserProfile再到头像昵称填写获取用户头像昵称全部尝试了一遍 怪就怪自己一开始没仔细看官方文档 没注意到小程序的官方公告 不多说了 整理一下
  • LCD图片显示、触摸屏、音乐播放、缩放图片和播放视频

    一 GEC6818开发板的LCD 1 LCD 1 原理 LCD屏幕是由一个个像素组成的 横向像素个数和纵向像素个数是LCD的一个重要指标 称为像素分辨率 当前举例开发板的分辨率是 800X480 LCD显示从屏幕左上角的像素开始 直到右下角
  • C0223 [2015普及组-B]扫雷游戏-C语言写

    题目描述 扫雷游戏是一款十分经典的单机小游戏 在n行m列的雷区中有一些格子含有地雷 称之为地雷格 其他格子不含地雷 称之为非地雷格 玩家翻开一个非地雷格时 该格将会出现一个数字 提示周围格子中有多少个是地雷格 游戏的目标是在不翻出任何地雷格
  • wget命令详解,断点续传

    1 支持断点下传功能 2 同时支持FTP和HTTP下载方式 3 支持代理服务器 4 设置方便简单 5 程序小 完全免费 wget虽然功能强大 但是使用起来还是比较简单的 基本的语法是 wget 参数列表 URL 下面就结合具体的例子来说明一
  • CSDN新星计划/原力计划来喽,对此你有何期待

    文章目录 写在前面 新星计划 独自开 原力计划 横穿全年的计划 写在最后 写在前面 哈喽 大家好 我是几何心凉 这是一份全新的专栏 得到CSDN王总的授权 来对于我们每周四的绿萝时间 直达CSDN 直播内容进行总结概括 让大家能够省去看直播
  • 【虚幻】在UE4使用c++的Timeline和Curve制作动画

    文章目录 虚幻 在UE4使用c 的Timeline和Curve制作动画 动画的必备要素 Curve Timeline 调用流程 代码示例 虚幻 在UE4使用c 的Timeline和Curve制作动画 想用c 在UE4里面写一个动画 Goog
  • LeetCode 98 验证二叉搜索树(二叉搜索树的中序遍历为递增)

    题目 给定一个二叉树 判断其是否是一个有效的二叉搜索树 假设一个二叉搜索树具有如下特征 节点的左子树只包含小于当前节点的数 节点的右子树只包含大于当前节点的数 所有左子树和右子树自身必须也是二叉搜索树 示例 1 输入 2 1 3 输出 tr
  • “自顶向下,逐步求精“的程序设计方法

    在程序设计中 自顶向下 和 面向对象 是两类最重要也最基本的程序设计方法 今天我们先介绍 自顶向下 逐步求精 的程序设计方法 所谓 自顶向下 即是把一个抽象的 困难的大问题分解为若干个小问题 如果认为小问题仍然不够简单可行 就再进一步分解
  • 《机器学习》 周志华学习笔记第一章 绪论(课后习题)

    最近需要学习机器学习 有一点点基础但是很少 希望能通过写博客的方式和大家交流以及学习达到共同进步的目的 绪论 一 内容 1 基本术语 2 假设空间与版本空间 3 归纳偏好 常用的有奥卡姆剃刀 没有免费的午餐定理 No Free Lunch
  • Android离线文字识别-tesseract4android调用

    Android在线文字识别可以调阿里云的接口Android文字识别 阿里云OCR调用 花花的博客 CSDN博客 需要离线文字识别的话 可以调tesseract4android 个人测试效果不是特别理想 但是速度真的很快 VIVO S10后摄
  • 第20章 USART—串口通讯—零死角玩转STM32-F429系列

    第20章 USART 串口通讯 零死角玩转STM32 F429系列 第20章 USART 串口通讯 全套200集视频教程和1000页PDF教程请到秉火论坛下载 www firebbs cn 野火视频教程优酷观看网址 http i youku
  • 中缀表达式求值问题

    1 有无括号 2 一种优先级运算符 只有 或 还是2种 和 都有 3 求逆波兰序列 求值 求表达式树 两种思路 1 分治 求值 和求表达式树都可以用 nlogn 1 先去掉冗余括号 两边最外面的 如 1 1 2 如果有的话 找到优先级最小的