166. 分数到小数

953 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动

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"

解题思路

模拟长除法,使用map记录余数出现的位置,一旦出现相同余数,说明后面就是循环部分了,就可以添加括号了。

  • 最小负数转为正数的时候会溢出,因此要使用long去接

代码

class Solution {
    public String fractionToDecimal(int num, int de) {

        if(num==0) return "0";
        StringBuilder sb=new StringBuilder();
        if(num<0^de<0)
            sb.append('-');
        long numL=Math.abs(Long.valueOf(num));
        long deL=Math.abs(Long.valueOf(de));
        sb.append(numL/deL);
        long re=numL%deL;
        if(re==0)
            return sb.toString();
        sb.append('.');
        HashMap<Long,Integer> map=new HashMap<>();
        while(re!=0)
        {
            if(map.containsKey(re))
            {
                sb.insert(map.get(re), "(");
                sb.append(')');
                return sb.toString();
            }
            map.put(re,sb.length());
            re*=10;
            sb.append(String.valueOf(re/deL));
            re=re%de;
        }
        return sb.toString();
    }
}
  • 时间复杂度:O(len),其中 len 是答案字符串的长度,这道题中 len<=10000 。对于答案字符串中的每一个字符,计算时间都是 O(1)。

  • 空间复杂度:O(len),其中 len 是答案字符串的长度,这道题中 len<=10000 。空间复杂度主要取决于答案字符串和哈希表,哈希表中的每个键值对所对应的下标各不相同,因此键值对的数量不会超过 len.