跳转至

166. 分数到小数

题目描述

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

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

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

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

 

示例 1:

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

示例 2:

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

示例 3:

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

 

提示:

  • -231 <= numerator, denominator <= 231 - 1
  • denominator != 0

解法

方法一:数学 + 哈希表

我们首先判断 \(numerator\) 是否为 \(0\),如果是,则直接返回 "0"

接着我们判断 \(numerator\)\(denominator\) 是否异号,如果是,则结果为负数,我们将结果的第一个字符设为 "-"

然后我们将 \(numerator\)\(denominator\) 取绝对值,分别记为 \(a\)\(b\)。由于分子和分母的范围为 \([-2^{31}, 2^{31} - 1]\),直接取绝对值可能会溢出,因此我们将 \(a\)\(b\) 都转换为长整型。

接着我们计算整数部分,即 \(a\) 除以 \(b\) 的整数部分,将其转换为字符串并添加到结果中。然后我们将 \(a\) 取余 \(b\),记为 \(a\)

如果 \(a\)\(0\),说明结果为整数,直接返回结果。

接着我们计算小数部分,我们使用哈希表 \(d\) 记录每个余数对应的结果的长度。我们不断将 \(a\) 乘以 \(10\),然后将 \(a\) 除以 \(b\) 的整数部分添加到结果中,然后将 \(a\) 取余 \(b\),记为 \(a\)。如果 \(a\)\(0\),说明结果为有限小数,直接返回结果。如果 \(a\) 在哈希表中出现过,说明结果为循环小数,我们找到循环的起始位置,将结果插入括号中,然后返回结果。

时间复杂度 \(O(l)\),空间复杂度 \(O(l)\),其中 \(l\) 为结果的长度,本题中 \(l < 10^4\)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution:
    def fractionToDecimal(self, numerator: int, denominator: int) -> str:
        if numerator == 0:
            return "0"
        ans = []
        neg = (numerator > 0) ^ (denominator > 0)
        if neg:
            ans.append("-")
        a, b = abs(numerator), abs(denominator)
        ans.append(str(a // b))
        a %= b
        if a == 0:
            return "".join(ans)
        ans.append(".")
        d = {}
        while a:
            d[a] = len(ans)
            a *= 10
            ans.append(str(a // b))
            a %= b
            if a in d:
                ans.insert(d[a], "(")
                ans.append(")")
                break
        return "".join(ans)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Solution {
    public String fractionToDecimal(int numerator, int denominator) {
        if (numerator == 0) {
            return "0";
        }
        StringBuilder sb = new StringBuilder();
        boolean neg = (numerator > 0) ^ (denominator > 0);
        sb.append(neg ? "-" : "");
        long a = Math.abs((long) numerator), b = Math.abs((long) denominator);
        sb.append(a / b);
        a %= b;
        if (a == 0) {
            return sb.toString();
        }
        sb.append(".");
        Map<Long, Integer> d = new HashMap<>();
        while (a != 0) {
            d.put(a, sb.length());
            a *= 10;
            sb.append(a / b);
            a %= b;
            if (d.containsKey(a)) {
                sb.insert(d.get(a), "(");
                sb.append(")");
                break;
            }
        }
        return sb.toString();
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Solution {
public:
    string fractionToDecimal(int numerator, int denominator) {
        if (numerator == 0) {
            return "0";
        }
        string ans;
        bool neg = (numerator > 0) ^ (denominator > 0);
        if (neg) {
            ans += "-";
        }
        long long a = abs(1LL * numerator), b = abs(1LL * denominator);
        ans += to_string(a / b);
        a %= b;
        if (a == 0) {
            return ans;
        }
        ans += ".";
        unordered_map<long long, int> d;
        while (a) {
            d[a] = ans.size();
            a *= 10;
            ans += to_string(a / b);
            a %= b;
            if (d.contains(a)) {
                ans.insert(d[a], "(");
                ans += ")";
                break;
            }
        }
        return ans;
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
func fractionToDecimal(numerator int, denominator int) string {
    if numerator == 0 {
        return "0"
    }
    ans := ""
    if (numerator > 0) != (denominator > 0) {
        ans += "-"
    }
    a := int64(numerator)
    b := int64(denominator)
    a = abs(a)
    b = abs(b)
    ans += strconv.FormatInt(a/b, 10)
    a %= b
    if a == 0 {
        return ans
    }
    ans += "."
    d := make(map[int64]int)
    for a != 0 {
        if pos, ok := d[a]; ok {
            ans = ans[:pos] + "(" + ans[pos:] + ")"
            break
        }
        d[a] = len(ans)
        a *= 10
        ans += strconv.FormatInt(a/b, 10)
        a %= b
    }
    return ans
}

func abs(x int64) int64 {
    if x < 0 {
        return -x
    }
    return x
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function fractionToDecimal(numerator: number, denominator: number): string {
    if (numerator === 0) {
        return '0';
    }
    const sb: string[] = [];
    const neg: boolean = numerator > 0 !== denominator > 0;
    sb.push(neg ? '-' : '');
    let a: number = Math.abs(numerator),
        b: number = Math.abs(denominator);
    sb.push(Math.floor(a / b).toString());
    a %= b;
    if (a === 0) {
        return sb.join('');
    }
    sb.push('.');
    const d: Map<number, number> = new Map();
    while (a !== 0) {
        d.set(a, sb.length);
        a *= 10;
        sb.push(Math.floor(a / b).toString());
        a %= b;
        if (d.has(a)) {
            sb.splice(d.get(a)!, 0, '(');
            sb.push(')');
            break;
        }
    }
    return sb.join('');
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class Solution {
    public string FractionToDecimal(int numerator, int denominator) {
        if (numerator == 0) {
            return "0";
        }
        StringBuilder sb = new StringBuilder();
        bool neg = (numerator > 0) ^ (denominator > 0);
        sb.Append(neg ? "-" : "");
        long a = Math.Abs((long)numerator), b = Math.Abs((long)denominator);
        sb.Append(a / b);
        a %= b;
        if (a == 0) {
            return sb.ToString();
        }
        sb.Append(".");
        Dictionary<long, int> d = new Dictionary<long, int>();
        while (a != 0) {
            d[a] = sb.Length;
            a *= 10;
            sb.Append(a / b);
            a %= b;
            if (d.ContainsKey(a)) {
                sb.Insert(d[a], "(");
                sb.Append(")");
                break;
            }
        }
        return sb.ToString();
    }
}

评论