zoukankan      html  css  js  c++  java
  • 592. Fraction Addition and Subtraction

    Problem statement:

    Given a string representing an expression of fraction addition and subtraction, you need to return the calculation result in string format. The final result should be irreducible fraction. If your final result is an integer, say 2, you need to change it to the format of fraction that has denominator 1. So in this case, 2 should be converted to 2/1.

    Example 1:

    Input:"-1/2+1/2"
    Output: "0/1"

    Example 2:

    Input:"-1/2+1/2+1/3"
    Output: "1/3"

    Example 3:

    Input:"1/3-1/2"
    Output: "-1/6"

    Example 4:

    Input:"5/3+1/3"
    Output: "2/1"

    Note:

    1. The input string only contains '0' to '9''/''+' and '-'. So does the output.
    2. Each fraction (input and output) has format ±numerator/denominator. If the first input fraction or the output is positive, then '+' will be omitted.
    3. The input only contains valid irreducible fractions, where the numerator and denominator of each fraction will always be in the range [1,10]. If the denominator is 1, it means this fraction is actually an integer in a fraction format defined above.
    4. The number of given fractions will be in the range [1,10].
    5. The numerator and denominator of the final result are guaranteed to be valid and in the range of 32-bit int.

    Solution one: DFS from back to front(AC)

    The input is an expression in the format of string. We need to divide the entire problem into small size. By the rules of addition associative law, we can not loop from front to back since the sign need to reverse if it is negative. So, looping from back to front is a good idea. 

    DFS model:

    In this problem, I choose the DFS template with a return value(string). 

    In each level, I get a string representing a fraction, add it with the return value from the lower level and return the sum(string) to upper level.

    In order to get the string fraction in current level, I stop at '+', '-' or the beginning position of the string(this is only useful when the first number in the string is positive).

    For the purpose of a readable code, there are two functions, one function adds two string fractions and returns a string, another gets the greatest common divisor of two positive integers and return a positive integer.

    Some knowledge need to be remembered, these are all I met when I coded:

    • sscanf function:int sscanf ( const char * s, const char * format, ...);
    • this function inherits from C style, the first element is const char *.
    • string::resize(): return value is void, it can not be passed into a function as a parameter.
    • Greatest Common Divisor(GCD): in order to get the correct GCD, both inputs are positive.

    Time complexity is O(n). n is the size of the input string.

    class Solution {
    public:
        string fractionAddition(string expression) {
            if(expression.empty()){
                return "0/1";
            }
            string second;
            for(int i = expression.size() - 1; i >= 0; i--){
                if(expression[i] == '+' || expression[i] == '-' || i == 0){
                    second = expression.substr(i);
                    break;
                }
            }
            // resize the string
            expression.resize(expression.size() - second.size());
            string first = fractionAddition(expression);
            return add(first, second);
        }
    private:
        string add(string first, string second){
            if(first.empty()){
                return second;
            }
            int fn = 0, fd = 0, sn = 0, sd = 0;
            // get the number from expression
            sscanf(first.c_str(), "%d/%d", &fn, &fd);
            sscanf(second.c_str(), "%d/%d", &sn, &sd);
            int numerator = fn * sd + fd * sn;
            int denominator = fd * sd;
            if(numerator == 0){
                return "0/1";
            }
            int gcd = get_gcd(abs(numerator), abs(denominator)); // all input must be position to get GCD
            return to_string(numerator/gcd) + "/" + to_string(denominator/gcd);
        }
        // get greatest common divisor
        // the two inputs should be positive
        int get_gcd(int a, int b){
            while(a != b){
                if(a > b){
                    a -= b;
                } else {
                    b -= a;
                }
            }
            return a;
        }
    };

    Solution two: 

    This solution is intuitive, extract all fractions including their sign from the expression and push them into a vector, add them together.

    Time complexity is O(n).

    class Solution {
    public:
        string fractionAddition(string expression) {
            vector<string> fractions;
            for(int i = 0, j = 1; j <= expression.size(); j++){
                if(j == expression.size() || expression[j] == '+' || expression[j] == '-'){
                    fractions.push_back(expression.substr(i, j - i));
                    i = j;
                }
            }
            string addition("0/1");
            for(auto fraction : fractions){
                addition = get_addition(addition, fraction);
            }
            return addition;
        }
    private:
        string get_addition(string first, string second){
            int fn = 0, fd = 0, sn = 0, sd = 0;
            // get the number from expression
            sscanf(first.c_str(), "%d/%d", &fn, &fd);
            sscanf(second.c_str(), "%d/%d", &sn, &sd);
            int numerator = fn * sd + fd * sn;
            int denominator = fd * sd;
            if(numerator == 0){
                return "0/1";
            }
            int gcd = get_gcd(abs(numerator), abs(denominator)); // all input must be position to get GCD
            return to_string(numerator/gcd) + "/" + to_string(denominator/gcd);
        }
        // get greatest common divisor
        // the two inputs should be positive
        int get_gcd(int a, int b){
            while(a != b){
                if(a > b){
                    a -= b;
                } else {
                    b -= a;
                }
            }
            return a;
        }
    };
  • 相关阅读:
    CKEditor4x word导入不保存格式的解决方案
    为了希望正式开始开发
    HTTP权威指南-URL与资源
    HTTP权威指南-HTTP概述
    同源策略和跨域访问
    普通Html文件图片上传(Storing Image To DB)
    PostgreSQL时间戳提取的特殊需求
    (转)百度前端规范、腾讯前端规范
    整理一下嵌入式WEB开发中的各种屏蔽(转)
    Excel表格指定列数据转换成文本
  • 原文地址:https://www.cnblogs.com/wdw828/p/6887595.html
Copyright © 2011-2022 走看看