题干
给定两个整数,分别表示分数的分子 numerator 和分母 denominator,以字符串形式返回小数。
如果小数部分为循环小数,则将循环的部分括在括号内。
示例 1:
输入: numerator = 1, denominator = 2
输出: "0.5"
示例 2:
输入: numerator = 2, denominator = 1
输出: "2"
示例 3:
输入: numerator = 2, denominator = 3
输出: "0.(6)"
想法
其实我们仔细回想一下我们人类计算小数的方法,就是每一位用除数除以被除数,然后将余数×10作为被除数,如此往复。
于是我的代码也是这个思路
只是有几个问题:
如果有溢出怎么办?
最简单的我们用long来玩儿,就不管溢出
如何判断是有循环的?
其实是这样一个道理,因为除数不变,如果被除数出现了之前出现过的数,那就会出现循环。
再两个重复之间的数作为循环体。
我的代码写的十分详细,直接看就行
Java代码
public class Solution {
public String fractionToDecimal(int numerator, int denominator) {
if(numerator==0) {return "0";}//被除数为0的情况
if(denominator==0){return String.valueOf(Integer.MAX_VALUE);}//除数为0的情况
HashMap<Long,Integer> map= new HashMap<>();//用hashmap来存这个数在小数点后的位置和值
List<Long> number=new ArrayList<>();//list来存整个数的每位
int index=0;//现在进行到哪个位置
int beginIndex=-1;//循环开始的位置
StringBuilder builder = new StringBuilder();
Long num=(long)numerator;//转换成long,下同
Long denum=(long)denominator;
if((num<0&&denum>0)||(num>0&&denum<0)){//如果异号,开头加负号
builder.append('-');}
num=Math.abs(num);//都取成正的,下同
denum=Math.abs(denum);
Long val=num/denum;//这一位的数
builder.append(String.valueOf(val));//第一位直接加进去,其实可以不要list直接加sb
num=(num%denum)*10;//余数×10作为被除数
while(num!=0){
if(!map.containsKey(num)){//如果hashmap里没有,证明没有出现过
map.put(num,index++);//加到hashmap
val=num/denum;
number.add(val);
num=(num%denum)*10;
}else{
beginIndex=map.get(num);//有的话,在list里找到这个数的位置,作为循环开始的位置
break;
}
}
for(int i=0;i<index;i++){
if(i==0) {builder.append('.');}//加小数点
if(i==beginIndex) {builder.append('(');}//循环体
builder.append(number.get(i));//将list的每一位加到sb
}
if(beginIndex!=-1){
builder.append(')');//循环结束,最后补一个)
}
return builder.toString(); }
}
优化
其实list可以不要,hashmap也可以使用有序的,以下是几个更好的代码(可读性可能没那么好
public String fractionToDecimal(int numerator, int denominator) {
if (numerator == 0) {
return "0";
}
StringBuilder fraction = new StringBuilder();
// If either one is negative (not both)
if (numerator < 0 ^ denominator < 0) {
fraction.append("-");
}
// Convert to Long or else abs(-2147483648) overflows
long dividend = Math.abs(Long.valueOf(numerator));
long divisor = Math.abs(Long.valueOf(denominator));
fraction.append(String.valueOf(dividend / divisor));
long remainder = dividend % divisor;
if (remainder == 0) {
return fraction.toString();
}
fraction.append(".");
Map<Long, Integer> map = new HashMap<>();
while (remainder != 0) {
if (map.containsKey(remainder)) {
fraction.insert(map.get(remainder), "(");
fraction.append(")");
break;
}
map.put(remainder, fraction.length());
remainder *= 10;
fraction.append(String.valueOf(remainder / divisor));
remainder %= divisor;
}
return fraction.toString();
}
此代码摘自https://blog.csdn.net/xushiyu1996818/article/details/86675730
class Solution {
public String fractionToDecimal(int numerator, int denominator) {
long lnumerator = Math.abs((long)numerator);
long ldenominator = Math.abs((long)denominator);
long r = lnumerator % ldenominator;
StringBuilder res =
new StringBuilder(((numerator != 0) && ((numerator > 0) ^ (denominator > 0)))? "-" : "");
res.append((lnumerator / ldenominator));
if(r == 0) return res.toString();
HashMap<Long, Integer> remains = new HashMap();
StringBuilder fraction = new StringBuilder();
while(r > 0 && !remains.containsKey(r)){
remains.put(r, fraction.length());
r *= 10;
fraction.append(r / ldenominator);
r = r % ldenominator;
}
if(remains.containsKey(r)){
int recur_pos = remains.get(r);
fraction.insert((int)remains.get(r), '(').append(')');
}
return res.append('.').append(fraction).toString();
}
}
此代码摘自leetcode官网
总结
题还是蛮有意思的,就是sima leetcode现在在线编译如果编译不通过不报错误位置了…
差评!