[Mnsx_x]刷题笔记——分数到小数
给定两个整数,分别表示分数的分子 numerator 和分母 denominator,以 字符串形式返回小数。
如果小数部分为循环小数,则将循环的部分括在括号内。
如果存在多个答案,只需返回任意一个。
对于所有给定的输入,保证答案字符串的长度小于 104 。
题目解析
题目要求就是现实中除法的实现,主要的难点是无限循环小数如何去判断,负数的处理,另外因为可能有溢出的可能,应该使用long来装载,执行过程大概是,用被除数除以除数,如果不能整除,那么余数*10,作为被除数循环执行,直到余数为零停止,或者作为无限循环返回。
思路一——模拟
看到这道题后第一想法就是用模拟算法进行处理,模拟除法的流程进行解决,首先**判断是否能够整除,如果能够整除那么就直接返回结果,如果不能整除那么先判断是否为负数,决定是否需要将负号添加到StringBuffer中,整数部分直接对两数进行相除即可,向StringBuffer中添加小数点后,进入小数部分的计算,使用HashMap来记录出现的余数,当出现相同的余数则说明存在无限循环,那么就返回无限循环的格式,直到被除数也就是余数等于0时返回StringBuffer中的字符串。
class Solution {
public String fractionToDecimal(int numerator, int denominator) {
//实例化StringBuffer
StringBuffer sb = new StringBuffer();
//使用long型来装载防止溢出
long a = numerator, b = denominator;
//判断是否能够整除
if(a % b == 0){
return String.valueOf(a / b);
}
//判断结果是否为负
if(a * b < 0){
sb.append("-");
a = Math.abs(a);
b = Math.abs(b);
}
//将整数部分添加到StringBuffer中
sb.append(String.valueOf(a / b));
//添加小数点
sb.append(".");
//修改被除数的值, 用余数替代
a %= b;
//实例化Map来判断余数是否重复
Map<Long, Integer> map = new HashMap<>();
while(a != 0){
map.put(a, sb.length());
a *= 10;
sb.append(String.valueOf(a / b));
a %= b;
if(map.containsKey(a)){
int index = map.get(a);
return String.format("%s(%s)", sb.substring(0, index), sb.substring(index));
}
}
return sb.toString();
}
}
时间复杂度:O(n) n为字符串的长度
空间复杂度:O(n) n为字符串的长度