leetcode之166分数到小数Golang
题目描述
给定两个整数,分别表示分数的分子 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"
提示:
-231 <= numerator, denominator <= 231 - 1denominator != 0
算法
算法说来很容易,就是每次记录当前的余数,如果余数等于0,说明已经除尽了不是循环小数,如果当前余数在之前的余数中出现过,那么就说明出现了循环小数。使用数组来记录每一个商,使用map来记录余数以及对应的商在数组中的位置
最后只需要根据map在数组中重复余数的商在数组中位置index,那么数组中index之后的元素就是小数的循环部分
代码
func fractionToDecimal(numerator int, denominator int) string {
if numerator == 0 {
return "0"
}
signFlag := false
if numerator < 0 {
numerator = -numerator
signFlag = !signFlag
}
if denominator < 0 {
denominator = -denominator
signFlag = !signFlag
}
// 先计算出整数部分
integerN := numerator / denominator
// 再计算小数部分
floatN := numerator % denominator
quo := []int{integerN}
remin := map[int]int{floatN: 0}
reminFlag := false
var dot int
for {
// 余数为0,就直接返回,不是循环小数
if floatN == 0 {
reminFlag = !reminFlag
break
}
floatN *= 10
sInt := floatN / denominator
sFloat := floatN % denominator
quo = append(quo, sInt)
// 检查当前余数是否出现过,如果出现过,说明这就是循环小数
if _, ok := remin[sFloat]; ok {
dot = sFloat
break
}
floatN = sFloat
// 记录余数对应的商在数组中的位置
remin[sFloat] = len(quo) - 1
}
res := strconv.Itoa(integerN)
if reminFlag {
// 没有循环
if len(quo) > 1 {
// 有小数
res += "."
for index := 1; index < len(quo); index++ {
res += strconv.Itoa(quo[index])
}
}
if signFlag {
res = "-" + res
}
return res
}
// 有循环
loopIndex := remin[dot]
res += "."
for index := 1; index <= loopIndex; index++ {
res += strconv.Itoa(quo[index])
}
// 加入循环部分
res += "("
for index := loopIndex + 1; index < len(quo); index++ {
res += strconv.Itoa(quo[index])
}
res += ")"
if signFlag {
res = "-" + res
}
return res
}
浙公网安备 33010602011771号