题目

思路

本题可以拆解为几个小问题解决

1.符号的计算

2.小数点前整数部分的计算

3.小数点后小数的计算

(1)有限的小数,当余数为零时停止计算
(2)无限循环小数,当出现重复的数字时,将循环部分加入字符串
(3)无限不循环小数 ,由于分数为有理数,无需考虑该类小数

小数的具体计算方法可以使用竖式计算的长除法完成计算

代码

func fractionToDecimal(numerator, denominator int) string {
    if numerator%denominator == 0 {
        return strconv.Itoa(numerator / denominator)
    }

    s := []byte{}
    if numerator < 0 != (denominator < 0) {
        s = append(s, '-')
    }

    // 整数部分
    numerator = abs(numerator)
    denominator = abs(denominator)
    integerPart := numerator / denominator
    s = append(s, strconv.Itoa(integerPart)...)
    s = append(s, '.')

    // 小数部分
    indexMap := map[int]int{}
    remainder := numerator % denominator
    for remainder != 0 && indexMap[remainder] == 0 {
        indexMap[remainder] = len(s)
        remainder *= 10
        s = append(s, '0'+byte(remainder/denominator))
        remainder %= denominator
    }
    if remainder > 0 { // 有循环节
        insertIndex := indexMap[remainder]
        s = append(s[:insertIndex], append([]byte{'('}, s[insertIndex:]...)...)
        s = append(s, ')')
    }

    return string(s)
}

func abs(x int) int {
    if x < 0 {
        return -x
    }
    return x
}

复杂度分析

时间复杂度:O(l),其中 l 是答案字符串的长度,这道题中 l≤10^4 。对于答案字符串中的每一个字符,计算时间都是 O(1)。

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

03-05 14:15