给定两整数,分别表示分数的分子(numerator)和分母(denominator),请使用字符串形式返回小数。
如果小数为循环小数,则将循环的部分括在括号里面。对应给定的输入,保证答案字符串长度小于10000;
示例1:
输入:numerator = 4, denominator = 333
输出:"0.(012)"
这道题是:求小数(余数+求商)+找到循环小数。
对于求小数(余数+求商), 有以下操作流程:
对于找到循环小数,有以下操作流程:
最后是对结果的组装,如果有循环小数则需要组装循环小数,如果没有则直接返回结果。这里组装循环小数是使用了StringBuilder.insert()函数,避免拷贝数据带来的性能损耗。
-
- import java.util.HashMap;
- import java.util.Map;
-
- class Solution {
- public String fractionToDecimal(int numerator, int denominator) {
- // 类型强转,避免溢出
- return fractionToDecimal((long) numerator, (long) denominator);
- }
-
- public String fractionToDecimal(long numerator, long denominator) {
-
- // 数据预先处理,先获得整数部分,并且确定符号类型
- long v = numerator / denominator;
- StringBuilder sb = new StringBuilder(10);
- if (v == 0) {
- if (numerator > 0 && denominator < 0 || numerator < 0 && denominator > 0) {
- sb.append("-");
- }
- sb.append('0');
- } else {
- sb.append(v);
- }
-
- numerator = Math.abs(numerator % denominator);
- if (numerator != 0) {
- sb.append(".");
- }
- denominator = Math.abs(denominator);
-
-
- int start = sb.length();
- // 创建modMap记录每个mod的位置
- Map
modMap = new HashMap<>(); - while (numerator != 0 && modMap.get(numerator) == null) {
-
- //记录每个mod的位置
- modMap.put(numerator, start);
-
- // 计算分数
- numerator *= 10;
- sb.append(numerator / denominator);
-
- // 重新生成分子
- numerator %= denominator;
- start++;
- }
-
- // 判断是否存在循环小数
- Integer index = modMap.get(numerator);
- if (index != null) {
- // 使用insert操作,降低耗时
- sb.insert(index.intValue(), '(').append(')');
- }
- return sb.toString();
- }
-
- public static void main(String[] args) {
- Solution solution = new Solution();
- System.out.println(solution.fractionToDecimal(4, -333));
- System.out.println(solution.fractionToDecimal(4, 333));
- System.out.println(solution.fractionToDecimal(1, 2));
- System.out.println(solution.fractionToDecimal(2, 1));
- System.out.println(solution.fractionToDecimal(2, -1));
- }
-
- }
这道题就是一个数学题目,我主要的时间花在判断循环小数上,最终还是看了其他人的解决思路后才做出来的。
这个过程中遇到2个问题,一个是溢出问题,所以我这边最后使用long做计算。还有就是耗时问题,我开始是重新拷贝字符串再拼接循环小数,这样导致耗时很高,最后使用StringBuilder.insert耗时才降下来的。后续还是要多看看系统自带库函数,目前看都比自己实现的性能要好很多。如果有性能更好,设计更好的解决方案,欢迎回复。