给定两个整数,分别表示分数的分子 numerator 和分母 denominator,以字符串形式返回小数。
如果小数部分为循环小数,则将循环的部分括在括号内。
示例 1:
输入: numerator = 1, denominator = 2
输出: "0.5" 示例 2:
输入: numerator = 2, denominator = 1
输出: "2"
示例 3:
输入: numerator = 2, denominator = 3
输出: "0.(6)"
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/fraction-to-recurring-decimal 著作权归领扣网络所有。
算法
需要用一个哈希表记录余数出现在小数部分的位置,当你发现已经出现的余数,就可以将重复出现的小数部分用括号括起来。
再出发过程中余数可能为 0,意味着不会出现循环小数,立刻停止程序。
就像两数相除问题一样,主义考虑负分数以及极端情况。
1 public String fractionToDecimal(int numerator, int denominator) { 2 if(numerator == 0) return "0"; //分子为零返回“0” 3 4 StringBuilder res = new StringBuilder(); 5 6 if(numerator < 0 ^ denominator < 0) res.append("-"); 7 8 //int的取值范围为(-2147483648~2147483647) 9 //如果int负最大值除以负一:-2147483648/-1 = 2147483648 、 10 //或者-1/-2147483648 超出了范围,所以转为long型 11 12 long up = Math.abs(Long.valueOf(numerator)); //且变为正数,因为前面已经判断了加负号的情况 13 // int up = Math.abs(numerator); 14 long down = Math.abs(Long.valueOf(denominator)); 15 // int down = Math.abs(denominator); 16 //把整除部分先加上 17 res.append(String.valueOf(up/down)); 18 //记录余数 19 long remain = up%down; 20 if(remain == 0) return res.toString(); 21 res.append("."); //不能整除就要加小数点了 22 23 //创建一个map存余数和对应余数所在位置 24 Map<Long,Integer> map = new HashMap<>(); 25 while(remain != 0){ //余数为零的话说明小数后面除得尽! 26 if(map.containsKey(remain)){ //发现这个余数之前有记录即产生了循环,循环处理加() 27 res.insert(map.get(remain),"("); 28 res.append(")"); 29 break; 30 } 31 map.put(remain,res.length()); //记录当前余数和得到该余数的下一个分位,举个例子2/3就明白了 32 remain *=10; //余数加零再除 33 res.append(String.valueOf(remain/down)); 34 remain %= down; //余数加零再求余 35 36 } 37 return res.toString(); 38 }