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

符号运算(华为OD)

输入描述
字符串格式的表达式,仅支持±*/,数字可能超过两位,可能带有空格,没有负数。长度小于200个字符。

输出描述
表达式结果,以最简格式表达 如果结果为整数,那么直接输出整数 如果结果为分数,那么分子分母不可再约分,可以为假分数,不可表达为带分数 结果可能是负数, 负号放在最前面。

示例1
输入:
1 + 5 * 7 / 8
输出:
43/8

示例2
输入:
1 / (0-5)
输出:
-1/5

示例3
输入:
1 * (3*4/(8-(7+0)))
输出:
12

示例4
输入:
(1+2)*3-4/2
输出:
7

package com.study.algorithm.huaweiOrOD.huaweiOD202509082334.符号运算;import java.util.*;/*** @ProjectName: 算法* @ClassName: Main* @Description: 符号运算* @Author: Tony_Yi* @Date: 2025/10/4 11:05* @Version 1.0**/
public class Main {public static void main(String[] args) {// 1. 创建Scanner对象,用于读取控制台输入Scanner scan = new Scanner(System.in);// 2. 创建Solution实例(核心计算逻辑的载体)Solution solution = new Solution();try {// 3. 读取输入:去掉所有空格(避免"1 + 2"这类带空格的输入影响解析)String res = scan.nextLine().replaceAll(" ", "");// 4. 计算并打印结果:字符串转字符数组传给calculate,结果自动调用Fraction的toString()格式化System.out.println(solution.calculate(res.toCharArray()));} catch (Exception e) {// 5. 捕获所有异常(如除零错误、表达式格式错误),输出"Error"System.out.println("Error");}}
}class Solution {// 存储运算符优先级:key=运算符,value=优先级(数字越大优先级越高)Map<Character, Integer> map;// 构造方法:初始化运算符优先级public Solution() {this.map = new HashMap<>();this.map.put('+', 1);  // 加减优先级1(低)this.map.put('-', 1);this.map.put('*', 2);  // 乘除优先级2(高)this.map.put('/', 2);}public Fraction calculate(char[] cs) {int n = cs.length;  // 表达式长度// 双栈初始化:Deque<Fraction> nums = new ArrayDeque<>();  // 数字栈(存分数对象)Deque<Character> ops = new ArrayDeque<>();  // 运算符栈(存运算符/括号)// 关键初始化:添加0到数字栈,处理表达式以负数开头的情况(如"-1+2" → "0-1+2")nums.addLast(new Fraction(0, 1));// 遍历表达式的每个字符for (int i = 0; i < n; i++) {char c = cs[i];// 情况1:遇到左括号'(' → 直接压入运算符栈(等待右括号触发计算)if (c == '(') {ops.addLast(c);} else if (c == ')') {// 情况2:遇到右括号')' → 计算到最近的左括号为止// 循环弹出运算符并计算,直到栈顶是'('while (!ops.isEmpty()) {if (ops.peekLast() != '(') {  // 栈顶不是左括号 → 计算calc(nums, ops);} else {  // 遇到左括号 → 弹出左括号(括号内计算完成),退出循环ops.pollLast();break;}}} else {// 情况3:既不是括号 → 数字或运算符// 子情况3.1:当前字符是数字 → 解析连续数字(处理多位数,如"123")if (isNumber(c)) {int u = 0;  // 存储解析出的整数int j = i;  // 从当前位置i开始,遍历连续数字while (j < n && isNumber(cs[j])) {// 字符转数字:'0'的ASCII码是48,cs[j]-'0'得到实际数字(如'5'-'0'=5)u = u * 10 + (cs[j++] - '0');}// 整数转分数(分子=u,分母=1),压入数字栈nums.addLast(new Fraction(u, 1));i = j - 1;  // i跳至最后一个数字的位置(避免循环重复处理)} else {// 子情况3.2:当前字符是运算符(+、-、*、/)// 关键处理:避免运算符前无数字的情况(如"(+1)"→"(0+1)"、"1+-2"→"1+0-2")if (i > 0 && (cs[i - 1] == '(' || cs[i - 1] == '+' || cs[i - 1] == '-')) {nums.addLast(new Fraction(0, 1));  // 补0到数字栈}// 处理运算符优先级:栈顶运算符优先级≥当前运算符 → 先计算栈顶(先乘除后加减)while (!ops.isEmpty() && ops.peekLast() != '(') {char prevOp = ops.peekLast();  // 栈顶运算符// 栈顶优先级更高或相等 → 计算if (map.get(prevOp) >= map.get(c)) {calc(nums, ops);} else {break;  // 栈顶优先级低,停止计算,当前运算符等待后续处理}}// 当前运算符压入运算符栈ops.addLast(c);}}}// 遍历结束后,运算符栈可能还有剩余运算符 → 逐个计算while (!ops.isEmpty()) {calc(nums, ops);}// 数字栈的最后一个元素就是最终结果return nums.peekLast();}void calc(Deque<Fraction> nums, Deque<Character> ops) {// 防御判断:至少需要2个操作数和1个运算符才能计算if (nums.size() < 2 || ops.isEmpty()) {return;}// 弹出操作数:注意顺序!后弹出的是第一个操作数(如"a+b",数字栈是[a,b],弹出b再弹出a)Fraction b = nums.pollLast();  // 第二个操作数(如"a-b"中的b)Fraction a = nums.pollLast();  // 第一个操作数(如"a-b"中的a)char op = ops.pollLast();      // 弹出运算符Fraction ans = null;  // 计算结果// 根据运算符调用Fraction的对应方法if (op == '+') {ans = a.add(b);      // 加法} else if (op == '-') {ans = a.subtract(b); // 减法(a - b,不是b - a)} else if (op == '*') {ans = a.multiply(b); // 乘法} else if (op == '/') {ans = a.divide(b);   // 除法}// 计算结果压回数字栈nums.addLast(ans);}boolean isNumber(char c) {return Character.isDigit(c);  // 调用Java内置方法判断}
}class Fraction {long fz;  // 分子(用long避免整数溢出,如1e9*1e9超出int范围)long fm;  // 分母// 构造方法:初始化分子和分母Fraction(long fz, long fm) {this.fz = fz;this.fm = fm;}Fraction add(Fraction other) {long nfz = this.fz * other.fm + other.fz * this.fm;long nfm = this.fm * other.fm;return new Fraction(nfz, nfm).simplify();}Fraction subtract(Fraction other) {long newFz = this.fz * other.fm - other.fz * this.fm;  // 新分子(a*d - c*b)long newFm = this.fm * other.fm;                        // 新分母return new Fraction(newFz, newFm).simplify();  // 化简后返回}Fraction multiply(Fraction other) {long newFz = this.fz * other.fz;  // 新分子(a*c)long newFm = this.fm * other.fm;  // 新分母(b*d)return new Fraction(newFz, newFm).simplify();  // 化简后返回}Fraction divide(Fraction other) {// 除零检查:other的分子为0 → 分数值为0,除法无意义if (other.fz == 0) {throw new ArithmeticException("Error");  // 抛异常,被Main捕获}long newFz = this.fz * other.fm;  // 新分子(a*d)long newFm = this.fm * other.fz;  // 新分母(b*c)return new Fraction(newFz, newFm).simplify();  // 化简后返回}Fraction simplify() {long gcdVal = gcd(this.fz, this.fm);  // 计算分子和分母的最大公约数// 分子分母同除以最大公约数,得到最简分数return new Fraction(this.fz / gcdVal, this.fm / gcdVal);}public long gcd(long a, long b) {return a % b == 0 ? b : gcd(b, a % b);}public String toString() {if (this.fm == 1) {// 分母为1 → 整数,直接输出分子(如3/1→"3")return Long.toString(this.fz);} else {// 分母不为1 → 拼接绝对值(避免"-3/-2"这类冗余符号)String base = Math.abs(this.fz) + "/" + Math.abs(this.fm);// 判断符号:分子分母异号(乘积<0)→ 加负号(如-3/2或3/-2→"-3/2")if (this.fz * this.fm < 0) {base = "-" + base;}return base;}}
}
http://www.dtcms.com/a/446005.html

相关文章:

  • C++微基础备战蓝桥杯之数组篇10.1
  • 美发店会员管理系统更新
  • HTB Attacking GraphQL Skills Assessment
  • 从化区城郊街道网站麻二村生态建设共青城市建设局网站
  • C# 调用 onnx格式的YOLOv11n模型
  • 使用PyTorch构建你的第一个神经网络
  • 数据结构哈希表--c
  • 腾云公司做网站赣州创可通科技有限公司
  • 大模型预训练深度解析:从基座构建到目标设计
  • 记一次网络io学习流水账
  • 网站建设与推广的实训报告天门网站网站建设
  • vue可以做pc的网站asp网站如何建设
  • YOLO11框架训练高光谱数据归一化问题
  • 宿迁网站定制有什么手机网站
  • 温州服务网站建设毕设用别人网站做原型
  • 八股文:计算机网络
  • MOVS 和MOVZ
  • llama.cpp RMSNorm CUDA 优化分析报告
  • 24ICPC成都站补题
  • DAY 41 简单CNN-2025.10.5
  • 网站建设的图片怎么加水印剪辑软件
  • 【c++】面 向 对 象 与 抽 象 数 据 类 型
  • 国内网站设计制作泰安招聘信息最新招聘2022
  • 第十二章:代理模式 - 访问控制的守护大师
  • 用wordpress建立学校网站网络营销软文案例
  • C++11线程相关
  • 住房和城乡建设统计网站网站开发公司需要招聘哪些人
  • 小土堆pytorch
  • 环保网站 中企动力建设专业的网站建设网络
  • 触摸未来2025.10.05:悟神经网络符号之伤,拥抱声音的宇宙