leetcode-分數加減法

/**
 * Created by feichen on 2018/6/11.
 * <p>
 * <p>
 * 給定一個表示分數加減運算表達式的字符串,你須要返回一個字符串形式的計算結果。 這個結果應該是不可約分的分數,即最簡分數。
 * 若是最終結果是一個整數,例如 2,你須要將它轉換成分數形式,其分母爲 1。因此在上述例子中, 2 應該被轉換爲 2/1。
 * <p>
 * 示例 1:
 * <p>
 * 輸入:"-1/2+1/2"
 * 輸出: "0/1"
 * 示例 2:
 * <p>
 * 輸入:"-1/2+1/2+1/3"
 * 輸出: "1/3"
 * 示例 3:
 * <p>
 * 輸入:"1/3-1/2"
 * 輸出: "-1/6"
 * 示例 4:
 * <p>
 * 輸入:"5/3+1/3"
 * 輸出: "2/1"
 * 說明:
 * <p>
 * 輸入和輸出字符串只包含 '0' 到 '9' 的數字,以及 '/', '+' 和 '-'。
 * 輸入和輸出分數格式均爲 ±分子/分母。若是輸入的第一個分數或者輸出的分數是正數,則 '+' 會被省略掉。
 * 輸入只包含合法的最簡分數,每一個分數的分子與分母的範圍是  [1,10]。 若是分母是1,意味着這個分數其實是一個整數。
 * 輸入的分數個數範圍是 [1,10]。
 * 最終結果的分子與分母保證是 32 位整數範圍內的有效整數。
 */
public class FractionAddition {

    static class Fraction {
        //符號
        TAG tag = TAG.POSITIVE;
        //分子
        int numerator;
        //分母
        int denominator;

        @Override
        public String toString() {
            return (tag == TAG.NEGATIVE ? "-" : "") + numerator + "/" + denominator;
        }
    }

    enum TAG {
        NEGATIVE,
        POSITIVE
    }

    public String fractionAddition(String expression) {
        List<Fraction> fractions = convert(expression);
        if (!fractions.isEmpty()) {
            fractions = calculate(fractions);
        }
        return !fractions.isEmpty() ? reduceFraction(fractions.get(0)).toString() : "";
    }

    /**
     * 計算
     *
     * @param fractions
     * @return
     */
    public static List<Fraction> calculate(List<Fraction> fractions) {
        if (fractions.isEmpty() || fractions.size() == 1) {
            return fractions;
        }
        Fraction last = fractions.get(fractions.size() - 1);
        Fraction last2 = fractions.get(fractions.size() - 2);

        int denominatorLcm = lcm(last.denominator, last2.denominator);

        int lastNumerator = last.numerator * (denominatorLcm / last.denominator);

        int last2Numerator = last2.numerator * (denominatorLcm / last2.denominator);

        if (last.tag == TAG.NEGATIVE) {
            lastNumerator = -lastNumerator;
        }

        if (last2.tag == TAG.NEGATIVE) {
            last2Numerator = -last2Numerator;
        }

        int numeratorResult = lastNumerator + last2Numerator;

        Fraction newFraction = new Fraction();
        newFraction.numerator = Math.abs(numeratorResult);
        newFraction.denominator = denominatorLcm;
        newFraction.tag = numeratorResult < 0 ? TAG.NEGATIVE : TAG.POSITIVE;

        fractions.remove(fractions.size() - 1);
        fractions.remove(fractions.size() - 1);

        fractions.add(newFraction);

        return calculate(fractions);
    }


    /**
     * 約分
     *
     * @param fraction
     * @return
     */
    public static Fraction reduceFraction(Fraction fraction) {
        if (fraction.numerator == 0) {
            fraction.denominator = 1;
            return fraction;
        }
        int gcd = gcd(fraction.numerator, fraction.denominator);
        if (gcd != 1) {
            fraction.numerator = fraction.numerator / gcd;
            fraction.denominator = fraction.denominator / gcd;
        }
        return fraction;
    }


    /**
     * 最大公約數
     *
     * @param a
     * @param b
     * @return
     */
    //a b 爲正整數
    public static int gcd(int a, int b) {
        if (a == b) {
            return a;
        }
        if (a < b) {
            return gcd(b, a);
        } else {
            if (((a & 1) == 0) && ((b & 1) == 0)) { //ab都爲偶數
                return gcd(a >> 1, b >> 1) << 1;
            } else if (((a & 1) == 0) && ((b & 1) == 1)) { //a爲偶數,b爲奇數
                return gcd(a >> 1, b);
            } else if (((a & 1) == 1) && ((b & 1) == 0)) { //a爲奇數,b爲偶數
                return gcd(a, b >> 1);
            } else { //ab都爲奇數
                return gcd(b, a - b);
            }
        }
    }

    /**
     * 最小公倍數
     *
     * @param a
     * @param b
     * @return
     */
    public static int lcm(int a, int b) {
        return a * b / gcd(a, b);
    }

    /**
     * 轉換
     *
     * @param expression
     * @return
     */
    public static List<Fraction> convert(String expression) {
        List<Fraction> fractions = new ArrayList<>();
        char[] chars = expression.toCharArray();

        for (int i = 0; i < chars.length; i++) {
            if (chars[i] == '/') {
                Fraction fraction = new Fraction();

                List<Character> numeratorCharList = new ArrayList<>();
                //分子處理
                for (int j = i - 1; j >= 0; j--) {
                    if (Character.isDigit(chars[j])) {
                        numeratorCharList.add(0, chars[j]);
                    } else {
                        if (chars[j] == '-') {
                            fraction.tag = TAG.NEGATIVE;
                        }
                        break;
                    }
                }
                List<Character> denominatorCharList = new ArrayList<>();
                for (int j = i + 1; j < chars.length; j++) {
                    if (Character.isDigit(chars[j])) {
                        denominatorCharList.add(chars[j]);
                    } else {
                        break;
                    }
                }
                String numeratorStr =
                        numeratorCharList.stream().map(e -> e.toString()).reduce((acc, e) -> acc + e).get();
                String denominatorStr =
                        denominatorCharList.stream().map(e -> e.toString()).reduce((acc, e) -> acc + e).get();

                fraction.numerator = Integer.valueOf(numeratorStr);
                fraction.denominator = Integer.valueOf(denominatorStr);
                fractions.add(fraction);
            }
        }
        return fractions;
    }

    public static void main(String[] args) {
        FractionAddition fractionAddition = new FractionAddition();
        System.out.println(fractionAddition.fractionAddition("-5/2+10/3+7/9"));
    }

}
相關文章
相關標籤/搜索