文章目录
前言
10月三日的每日一题打卡来了,先申明一下,这次的打卡没打卡的原因是由于我做出来的时候已经超过12点了,所以当天的打卡界面是一个灰色的界面鸭。至于为什么到今天才更新,这就是我的惰了。
打卡界面
原题题目
给定两个整数,分别表示分数的分子 numerator 和分母 denominator,以 字符串形式返回小数 。
如果小数部分为循环小数,则将循环的部分括在括号内。
如果存在多个答案,只需返回 任意一个 。
对于所有给定的输入,保证 答案字符串的长度小于 104 。
题目案例
解题思路
我看到这道题时,第一反应,我们直接将数据接收类型转换位double类型除以double类型,我们的数据不就是小数吗?但我做了也不少的leetCode题,我觉得它不会出这么SB的问题,果不其然,小丑竟是我自己。这道题的难点就在于无限不循环小数。到这里,我们可以尝试一下从人工模拟除法运算的过程,我们就可以知道「为什么不会出现“无限不循环小数”」,因为始终是对余数进行补零操作,再往下进行运算,而余数个数具有明确的上限(有限集)。所以根据抽屉原理,一直接着往下计算,最终结果要么是「出现相同余数」,要么是「余数为 00,运算结束」。那么我们怎么来保存这一块的无限不循环小数,就是我们目前所遇到的问题。这一个问题我说实话,想了不短的时间,也就是这个我超过了12点,导致当天的打卡时间超过了12点。我的第一想法就是把所有出现额数字保存下来,然后发现我不知道怎么保存下来,里面的小数数据是否循环。我就根据我做的除法运算,发现了另一个简单的方法,我能不能把每次的数据的余数保存下来,当我们的余数一样的时候,不就时循环开始的时候了吗?
说干就开干,代码整起。
根据题目提示,我们需要将数据换成long类型,防止溢出。
代码实现
此题代码的注意点
一个显然的条件是,如果本身两数能够整除,直接返回即可;
如果两个数有一个为“负数”,则最终答案为“负数”,因此可以起始先判断两数相乘是否小于 00,如果是,先往答案头部追加一个负号 -;
public String fractionToDecimal(int numerator, int denominator) {
// 转 long 计算,防止溢出,因为两个数据
long a = numerator, b = denominator;
// 如果本身能够整除,直接返回计算结果
if (a % b == 0) return String.valueOf(a / b);
StringBuilder sb = new StringBuilder();
//如果其一为负数,先追加负号
if (a * b < 0) sb.append('-');
a = Math.abs(a); b = Math.abs(b);
// 计算小数点前的部分,并将余数赋值给 a
sb.append(String.valueOf(a / b) + ".");
a %= b;
Map<Long, Integer> map = new HashMap<>();
while (a != 0) {
// 记录当前余数所在答案的位置,并继续模拟除法运算
map.put(a, sb.length());
a *= 10;
sb.append(a / b);
a %= b;
// 如果当前余数之前出现过,则将 [出现位置 到 当前位置] 的部分抠出来(循环小数部分)
if (map.containsKey(a)) {
int u = map.get(a);
return String.format("%s(%s)", sb.substring(0, u), sb.substring(u));
}
}
return sb.toString();
}
leetCode运行结果截图
Ps:每日一句毒鸡汤:所有抱怨社会不公和制度的人翻译过来只有一句话:请给我金钱,女人和社会地位。