• 592. 分数加减运算 : 表达式计算入门题


    题目描述

    这是 LeetCode 上的 592. 分数加减运算 ,难度为 中等

    Tag : 「表达式计算」、「模拟」

    给定一个表示分数加减运算的字符串 expression,你需要返回一个字符串形式的计算结果。

    这个结果应该是不可约分的分数,即最简分数。 如果最终结果是一个整数,例如  ,你需要将它转换成分数形式,其分母为  。所以在上述例子中,  应该被转换为 2/1

    示例 1:

    输入: expression = "-1/2+1/2"

    输出: "0/1"
    • 1

    示例 2:

    输入: expression = "-1/2+1/2+1/3"

    输出: "1/3"
    • 1

    示例 3:

    输入: expression = "1/3-1/2"

    输出: "-1/6"
    • 1

    提示:

    • 输入和输出字符串只包含  '0' 到  '9' 的数字,以及  '/', '+' 和  '-'
    • 输入和输出分数格式均为  ±分子/分母。如果输入的第一个分数或者输出的分数是正数,则  '+' 会被省略掉。
    • 输入只包含合法的最简分数,每个分数的分子与分母的范围是   。 如果分母是 ,意味着这个分数实际上是一个整数。
    • 输入的分数个数范围是
    • 最终结果的分子与分母保证是 位整数范围内的有效整数。

    表达式计算

    为了方便,令 expressions

    由于给定的表达式中只有 +-,因此无须考虑优先级问题,直接从前往后计算即可。

    使用变量 ans 代指计算过程中的结果,从前往后处理表达式 s,每次以 ±分子/分母 的形式取出当前操作数(若为表达式的首个操作数,且为正数时,需要手动补一个 +)。

    假设当前取出的操作数为 num,根据 ans 的情况进行运算:

    • ans 为空串,说明 num 是首个操作数,直接将 num 赋值给 ans 即可
    • ans 不为空串,此时计算 numans 的计算结果赋值给 ans

    考虑实现一个计算函数 String calc(String a, String b) 计算两个操作 ab 的结果,其中入参 ab 以及返回值均满足 ±分子/分母 形式。

    首先通过读取 ab 的首个字符,得到两操作数的正负情况。若为一正一负,通过交换的形式,确保 a 为正数,b 为负数。

    然后通过 parse 方法拆解出字符串操作数的分子和分母,parse 使用指针扫描的方式实现即可,以数组形式将结果返回(第 位为分子数值,第 位分母数值)。

    假设操作数 a 对应的值为 ,操作数的值为 ,先将其转换为 ,进行运算后,再通过求最大公约数 gcd 的方式进行化简。

    Java 代码:

    class Solution {
        public String fractionAddition(String s) {
            int n = s.length();
            char[] cs = s.toCharArray();
            String ans = "";
            for (int i = 0; i < n; ) {
                int j = i + 1;
                while (j < n && cs[j] != '+' && cs[j] != '-') j++;
                String num = s.substring(i, j);
                if (cs[i] != '+' && cs[i] != '-') num = "+" + num;
                if (!ans.equals("")) ans = calc(num, ans);
                else ans = num;
                i = j;
            }
            return ans.charAt(0) == '+' ? ans.substring(1) : ans;
        }
        String calc(String a, String b) {
            boolean fa = a.charAt(0) == '+', fb = b.charAt(0) == '+';
            if (!fa && fb) return calc(b, a);
            long[] p = parse(a), q = parse(b);
            long p1 = p[0] * q[1], q1 = q[0] * p[1];
            if (fa && fb) {
                long r1 = p1 + q1, r2 = p[1] * q[1], c = gcd(r1, r2);
                return "+" + (r1 / c) + "/" + (r2 / c);
            } else if (!fa && !fb) {
                long r1 = p1 + q1, r2 = p[1] * q[1], c = gcd(r1, r2);
                return "-" + (r1 / c) + "/" + (r2 / c);
            } else {
                long r1 = p1 - q1, r2 = p[1] * q[1], c = gcd(Math.abs(r1), r2);
                String ans = (r1 / c) + "/" + (r2 / c);
                if (p1 >= q1) ans = "+" + ans;
                return ans;
            }
        }
        long[] parse(String s) {
            int n = s.length(), idx = 1;
            while (idx < n && s.charAt(idx) != '/') idx++;
            long a = Long.parseLong(s.substring(1, idx)), b = Long.parseLong(s.substring(idx + 1));
            return new long[]{a, b};
        }
        long gcd(long a, long b) {
            return b == 0 ? a : gcd(b, a % b);
        }
    }
    • 1

    TypeScript 代码:

    function fractionAddition(s: string): string {
        const n = s.length
        let ans = ""
        for (let i = 0; i < n; ) {
            let j = i + 1
            while (j < n && s[j] != '+' && s[j] != '-') j++
            let num = s.substring(i, j)
            if (s[i] != '+' && s[i] != '-') num = "+" + num
            if (ans != "") ans = calc(num, ans)
            else ans = num
            i = j
        }
        return ans[0] == "+" ? ans.substring(1) : ans
    };
    function calc(a: string, b: string): string {
        const fa = a[0] == "+", fb = b[0] == "+"
        if (!fa && fb) return calc(b, a)
        const p = parse(a), q = parse(b)
        const p1 = p[0] * q[1], q1 = q[0] * p[1]
        if (fa && fb) {
            const r1 = p1 + q1, r2 = p[1] * q[1], c = gcd(r1, r2)
            return "+" + (r1 / c) + "/" + (r2 / c)
        } else if (!fa && !fb) {
            const r1 = p1 + q1, r2 = p[1] * q[1], c = gcd(r1, r2)
            return "-" + (r1 / c) + "/" + (r2 / c)
        } else {
            const r1 = p1 - q1, r2 = p[1] * q[1], c = gcd(Math.abs(r1), r2)
            let ans = (r1 / c) + "/" + (r2 / c)
            if (p1 > q1) ans = "+" + ans
            return ans
        }
    }
    function parse(s: string): number[] {
        let n = s.length, idx = 1
        while (idx < n && s[idx] != "/") idx++
        const a = Number(s.substring(1, idx)), b = Number(s.substring(idx + 1))
        return [a, b]
    }
    function gcd(a: number, b: number): number {
        return b == 0 ? a : gcd(b, a % b)
    }
    • 1
    • 时间复杂度:
    • 空间复杂度:

    加餐 & 加练

    加餐一道更贴合笔试面试的「表达式计算」问题 : 双栈 : 表达式计算问题的通用解法 🎉🎉

    最后

    这是我们「刷穿 LeetCode」系列文章的第 No.592 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。

    在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。

    为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode 。

    在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。

    更多更全更热门的「笔试/面试」相关资料可访问排版精美的 合集新基地 🎉🎉

    本文由 mdnice 多平台发布

  • 相关阅读:
    油罐清洗抽吸系统设计
    Docker启动失败报错Failed to start Docker Application Container Engine解决方案
    剑指offer专项突击版第22天
    电大搜题——赋能学习,助力广东开放大学学子
    c#如何把字符串中的指定字符删除
    配置OSPF特殊区域
    以太坊智能合约的技术与组件
    [Windows 10]Qt5.14.2下安卓开发环境配置
    腾讯云数据库SaaS致力于构建数据库分布式云,为更多更广的用户提供服务
    Python编程陷阱(七)
  • 原文地址:https://blog.csdn.net/weixin_33243821/article/details/126010937