• LeetCode 0592. 分数加减运算:手把手分步のC++讲解


    【LetMeFly】592.分数加减运算:手把手分步のC++讲解

    力扣题目链接:https://leetcode.cn/problems/fraction-addition-and-subtraction/

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

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

     

    示例 1:

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

       示例 2:

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

        示例 3:

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

           

          提示:

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

          方法一:C++模拟

          pair表示分数,然后不断模拟即可。

          主要需要实现三个功能:

          1. 字符串转分数
            字符串转分数稍微复杂一些。
            首先根据字符串的首个字符判断分数的正负,然后计算分子和分母分别对应字符串中的哪几个字符,最后再把字符串转为int即可。
            pii string2fraction(string s) {
            	pii ans;
            	// 判断分数的正负
            	if (s[0] == '-') {
            		ans.first = -1;
            	}
            	else {
            		ans.first = 1;
            	}
            	// 计算分子开始位置的下标
            	int l = 0;
            	if (s[0] == '-' || s[0] == '+') {
            		l++;
            	}
            	// 计算分子结束位置的下标
            	int r = l;
            	while (s[r] != '/')
            		r++;
            	// 计算分子分母
            	ans.first *= atoi(s.substr(l, r - l).c_str());
            	ans.second = atoi(s.substr(r + 1, s.size() - r -1).c_str());
            	return ans;
            }
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
            • 16
            • 17
            • 18
            • 19
            • 20
            • 21
            • 22
            • 23
          2. 两个分数相加
            分数相加首先要通分。
            令新的分母为原本两个分数的最小公倍数,然后将两个分数的分子分别化为通分后的值并累加,最后进行约分即可。
            注意分子分母约分的时候,__gcd()函数调用时记得传入分子分母的绝对值,否则求得的最小公倍数可能会为负数。
            pii add(pii p1, pii p2) {
                pii ans;
                ans.second = p1.second * p2.second / __gcd(p1.second, p2.second);
                ans.first = p1.first * (ans.second / p1.second) + p2.first * (ans.second / p2.second);
                int gcd = __gcd(abs(ans.first), ans.second);
                ans.first /= gcd, ans.second /= gcd;
                return ans;
            }
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
          3. 将分数转为字符串
            这个功能实现起来相对容易,只需要将分子分母分别转为字符串,并在中间加上/即可。
            string fraction2string(pii f) {
                return to_string(f.first) + "/" + to_string(f.second);
            }
            
            • 1
            • 2
            • 3

          实现了上述三个功能,只需要在主函数中对原始字符串按加减号进行分割,并把每个分割出来的分数的值累加即可。

          string fractionAddition(string expression) {
          	pii ans = {0, 1};
          	int last = 0;  // 上一个处理到的字符的位置
          	for (int i = 1; i < expression.size(); i++) {
          		if (expression[i] == '+' || expression[i] == '-') {  // 遇到加减号就开始分割
          			ans = add(ans, string2fraction(expression.substr(last, i - last)));
          			last = i;
          		}
          	}
          	ans = add(ans, string2fraction(expression.substr(last, expression.size() - last)));  // 注意字符串末尾没有加减号,不要把最后一个分数遗漏了。
          	return fraction2string(ans);
          }
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12

          拓展:

          如果想要debug分数长啥样,可以直接重载运算符<<

          ostream &operator << (ostream& out, pii& p) {
              out << p.first << "/" << p.second;
              return out;
          }
          
          • 1
          • 2
          • 3
          • 4

          这样,当想要debug时,就可以直接

          pair<int, int> fraction = {1, 2};
          cout << fraction << endl;
          
          • 1
          • 2

          了。

          • 时间复杂度 O ( n ) O(n) O(n),其中 n n n是字符串长度
          • 空间复杂度 O ( m ) O(m) O(m),其中 m m m是一个分数的字符串的平均长度

          AC代码

          C++

          typedef pair<int, int> pii;
          
          ostream &operator << (ostream& out, pii& p) {
              out << p.first << "/" << p.second;
              return out;
          }
          
          class Solution {
          private:
              pii string2fraction(string s) {
                  pii ans;
                  if (s[0] == '-') {
                      ans.first = -1;
                  }
                  else {
                      ans.first = 1;
                  }
                  int l = 0;
                  if (s[0] == '-' || s[0] == '+') {
                      l++;
                  }
                  int r = l;
                  while (s[r] != '/')
                      r++;
                  ans.first *= atoi(s.substr(l, r - l).c_str());
                  ans.second = atoi(s.substr(r + 1, s.size() - r - 1).c_str());
          
                  // cout << s << " -> " << ans << endl;
          
                  return ans;
              }
          
              pii add(pii p1, pii p2) {
                  pii ans;
                  ans.second = p1.second * p2.second / __gcd(p1.second, p2.second);
                  ans.first = p1.first * (ans.second / p1.second) + p2.first * (ans.second / p2.second);
                  int gcd = __gcd(abs(ans.first), ans.second);
                  ans.first /= gcd, ans.second /= gcd;
                  return ans;
              }
          
              string fraction2string(pii f) {
                  return to_string(f.first) + "/" + to_string(f.second);
              }
          public:
              string fractionAddition(string expression) {
                  pii ans = {0, 1};
                  int last = 0;
                  for (int i = 1; i < expression.size(); i++) {
                      if (expression[i] == '+' || expression[i] == '-') {
                          ans = add(ans, string2fraction(expression.substr(last, i - last)));
                          last = i;
                      }
                  }
                  ans = add(ans, string2fraction(expression.substr(last, expression.size() - last)));
                  return fraction2string(ans);
              }
          };
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31
          • 32
          • 33
          • 34
          • 35
          • 36
          • 37
          • 38
          • 39
          • 40
          • 41
          • 42
          • 43
          • 44
          • 45
          • 46
          • 47
          • 48
          • 49
          • 50
          • 51
          • 52
          • 53
          • 54
          • 55
          • 56
          • 57
          • 58

          同步发文于CSDN,原创不易,转载请附上原文链接哦~
          Tisfy:https://letmefly.blog.csdn.net/article/details/126011320

        • 相关阅读:
          新知同享 | AI 开发广泛应用,高效构建
          PwnLab: init-文件包含、shell反弹、提权--靶机渗透思路讲解
          【GlobalMapper精品教程】030:栅格重采样案例教程(航测DSM)
          专精特新新企业技术创新发展趋势研究分析讲座详情
          Java8 Stream源码精讲(四):一文说透四种终止操作
          贪心算法之加油问题
          Oracle中的索引碎片
          C专家编程 第2章 这不是Bug,而是语言特性 2.3 误做之过
          flask-sqlalchemy库
          数据结构学习笔记(第一章绪论)
        • 原文地址:https://blog.csdn.net/Tisfy/article/details/126011320