/** * 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")); } }