题目
思路
本题可以拆解为几个小问题解决
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。