问题:
Given two integers representing the numerator and denominator of a fraction, return the fraction in string format.
If the fractional part is repeating, enclose the repeating part in parentheses.
For example,
- Given numerator = 1, denominator = 2, return "0.5".
- Given numerator = 2, denominator = 1, return "2".
- Given numerator = 2, denominator = 3, return "0.(6)".
解决:
【题意】
给定两个表示分数的分子和分母的整数,以字符串格式返回分数。
如果小数部分重复,则将重复部分括在括号内。
例如,
给定分子= 1,分母= 2,返回“0.5”。
给定分子= 2,分母= 1,返回“2”。
给定分子= 2,分母= 3,返回“0.(6)”
①
【解析】本题需要考虑以下问题:
1、如何循环求数?
可以看出,当余数开始循环时,商也会循环。我们每次都作除,然后取整数部分,然后余数*10,继续下去。
2、如何判断重复?
使用一个哈希表存储:key = 余数, value = 当前数位在小数得数中的位置。一旦找到重复的余数,就可以通过查找哈希表获得循环节的起点,从而得到小数的循环点。
3、如何结束循环?
只要包含有key或者除数为0时就可以停止了。
4、会不会溢出?
对待溢出最简单的解决方案是将其转换为更大的类型。
class Solution { //15ms
public String fractionToDecimal(int numerator, int denominator) {
if(numerator == 0) return "0";
if (denominator == 0) return "";
String res = "";
if ((numerator < 0) ^ (denominator < 0)){//结果为负数
res += "-";
}
long num = numerator;//将其转换为更大范围的数,避免溢出
long den = denominator;
num = Math.abs(num);//将其转换为整数
den = Math.abs(den);
long tmp = num / den;//结果为整数部分
res += String.valueOf(tmp);
long rem = (num % den) * 10;//余数部分
if (rem == 0) return res;//余数为0,则可以整除,返回结果
Map<Long,Integer> map = new HashMap<>();//保存余数及其对应的结果的位置
res += ".";
while(rem != 0){
if (map.containsKey(rem)){//如果前面已经出现过该余数,表示循环开始
int begin = map.get(rem);//循环体开始的地方
String part1 = res.substring(0,begin);
String part2 = res.substring(begin);
res = part1 + "(" + part2 + ")";
return res;
}
//继续往下除
map.put(rem,res.length());
tmp = rem / den;
res += String.valueOf(tmp);
rem = (rem % den) * 10;
}
return res;
}
}
② 在discuss中看到的解答,使用StringBuilder类保存结果。
class Solution {//3ms
public String fractionToDecimal(int numerator, int denominator) {
if(numerator == 0) return "0";
long num = (long)numerator;
long den = (long)denominator;
StringBuilder sb = new StringBuilder();
if(num * den < 0) sb.append("-");
num = Math.abs(num);
den = Math.abs(den);
sb.append(num / den);
if(num % den == 0) return sb.toString();
sb.append(".");
num = num % den;
Map<Long, Integer> map = new HashMap<>();
map.put(num, sb.length());
while(num != 0) {
num *= 10;
sb.append(num / den);
num = num % den;
if(map.containsKey(num)) {
sb.insert(map.get(num), "(");
sb.append(")");
return sb.toString();
}
map.put(num, sb.length());
}
return sb.toString();
}
}