Loading

Medium | LeetCode 166. 分数到小数 | 数学

166. 分数到小数

给定两个整数,分别表示分数的分子 numerator 和分母 denominator,以 字符串形式返回小数

如果小数部分为循环小数,则将循环的部分括在括号内。

如果存在多个答案,只需返回 任意一个

对于所有给定的输入,保证 答案字符串的长度小于 104

示例 1:

输入:numerator = 1, denominator = 2
输出:"0.5"

示例 2:

输入:numerator = 2, denominator = 1
输出:"2"

示例 3:

输入:numerator = 2, denominator = 3
输出:"0.(6)"

示例 4:

输入:numerator = 4, denominator = 333
输出:"0.(012)"

示例 5:

输入:numerator = 1, denominator = 5
输出:"0.2"

解题思路

模拟手动除法的运算。

在小数部分, 同样模拟手动除法的算法, 记录所有余数到HashMap里, 如果发生某个余数已经在HashMap存在了, 就认为是已经出现了无限循环, 需要将这部分用括号圈起来。

public String fractionToDecimal(int numerator, int denominator) {
    // 0 除以任何数都是 0
    if (numerator == 0) {
        return "0";
    }
    // 转成 long, 绕开整形溢出陷阱
    long dividend = numerator, divisor = denominator;
    boolean negitive = false;
    // 判断符号, 同正同负才是正, 否则是负
    if (numerator >= 0 ^ denominator >= 0) {
        negitive = true;
    }
    // 转为正数运算
    dividend = Math.abs(dividend);
    divisor = Math.abs(divisor);
    StringBuilder ans = new StringBuilder();
    // 负数
    if (negitive) {
        ans.append("-");
    }
    // 计算整数部分
    long quotient = dividend / divisor;
    // 加入整数部分
    ans.append(quotient);
    // 计算当前余数
    dividend = dividend % divisor;
    // 没有余数, 说明可以除尽, 没有小数部分
    if (dividend == 0) {
        return ans.toString();
    }
    int idx = -1, curPos = 0;
    Map<Long, Integer> map = new HashMap<>();
    // 下面是除法的手动模拟计算
    StringBuilder builder = new StringBuilder();
    while (dividend != 0) {
        // 余数 * 10 即为当前被除数
        dividend *= 10;
        // 如果当前被除数之前已经出现过了, 那么代表循环开始
        if (map.containsKey(dividend)) {
            // 获得循环节的位置
            idx = map.get(dividend);
            break;
        }
        // 更新 map
        map.put(dividend, curPos);
        // 记录当前结果
        builder.append(dividend / divisor);
        // 计算当前余数
        dividend %= divisor;
        // 更新小数指针位置
        curPos++;
    }

    String decmical = builder.toString();
    // 如果 map 中没有元素, 代表没有小数部分
    if (map.size() != 0) {
        ans.append(".");
    }
    // 存在循环节就加入括号, 否则直接加入小数部分
    if (idx != -1) {
        ans.append(decmical, 0, idx);
        ans.append("(");
        ans.append(decmical.substring(idx));
        ans.append(")");
    } else {
        ans.append(decmical);
    }
    return ans.toString();
}
posted @ 2021-04-06 14:42  反身而诚、  阅读(43)  评论(0编辑  收藏  举报