题目描述
给定两个整数,分别表示分数的分子 numerator 和分母 denominator,以字符串形式返回小数。
如果小数部分为循环小数,则将循环的部分括在括号内。
示例:
输入: numerator = 2, denominator = 3
输出: "0.(6)"
解题思路
这道题其实就是模拟我们平时在纸上竖式计算的过程,其中一些问题要注意下:符号部分、整数部分/小数部分、溢出的问题等。
HashMap
来处理重复值的技巧,经常用到了。
测试样例 | 解释 |
---|---|
0 1 \frac{0}{1} 10 | 被除数为 0。 |
1 0 \frac{1}{0} 01 | 除数为 0,应当抛出异常,这里为了简单起见不考虑。 |
20 4 \frac{20}{4} 420 | 答案是整数,不包括小数部分。 |
1 2 \frac{1}{2} 21 | 答案是 0.5,是有限小数。 |
− 1 4 \frac{-1}{4} 4−1或 1 − 4 \frac{1}{-4} −41 | 除数被除数有一个为负数,结果为负数。 |
− 1 − 4 \frac{-1}{-4} −4−1 | 除数和被除数都是负数,结果为正数。 |
− 2147483648 − 1 \frac{-2147483648}{-1} −1−2147483648 | 转成整数时注意可能溢出。 |
需要用一个哈希表记录余数出现在小数部分的位置(关键),当你发现已经出现的余数,就可以将重复出现的小数部分用括号括起来。
再出发过程中余数可能为 0,意味着不会出现循环小数,立刻停止程序。(小数部分如果“余数”重复出现就表示该小数是循环小数了)
就像两数相除问题一样(应该先做),主义考虑负分数以及极端情况,比如说 − 2147483648 − 1 \frac{-2147483648}{-1} −1−2147483648。
参考代码
typedef long long LL;
class Solution {
public:
//小数部分如果“余数”重复出现两次就表示该小数是循环小数了
string fractionToDecimal(int numerator, int denominator) {
if(denominator==0) return ""; // 边界条件,分母为0
if(numerator==0) return "0"; // 边界条件,分子为0
string result;
//转换为longlong防止溢出
long long num = (LL)numerator; // static_cast<long long>(numerator)
long long denom = (LL)denominator;
//处理正负号,一正一负取负号
if((num>0)^(denom>0))
result.push_back('-'); // 用 += 也行
//分子分母全部转换为正数(labs 处理长整形的绝对值)
num=labs(num); denom=labs(denom);
//处理整数部分
result.append(to_string(num/denom));
//处理小数部分
num %= denom; //获得余数
if(num==0) //余数为0,表示整除了,直接返回结果
return result;
result.push_back('.'); //余数不为0,添加小数点
int index = result.size()-1; //获得小数点的下标(重要),用length()也行
unordered_map<int, int> record; //map用来记录出现重复数的下标,然后将'('插入到重复数前面就好了
while(num && record.count(num) == 0){ //小数部分:余数不为0且余数还没有出现重复数字(如果因为余数为0退出循环,则代表是有限小数)
record[num] = ++index;
num *= 10; //余数扩大10倍,然后求商,和草稿本上运算方法是一样的
result += to_string(num/denom);
num %= denom; // 新的余数
}
if(record.count(num) == 1){ //出现循环余数,我们直接在重复数字前面添加'(',字符串末尾添加')'
result.insert(record[num], "(");
result.push_back(')');
}
return result;
}
};
自己提交的代码(看上面的注释版本就好)
typedef long long LL;
class Solution {
public:
string fractionToDecimal(int numerator, int denominator) {
if(denominator == 0)
return "";
if(numerator == 0)
return "0";
string res = "";
if((numerator > 0) ^ (denominator > 0))
res += "-";
LL numerator_ll = fabs((LL)numerator);
LL denominator_ll = fabs((LL)denominator);
res += to_string(numerator_ll / denominator_ll);
if(numerator_ll % denominator_ll == 0)
return res;
res += ".";
numerator_ll = numerator_ll % denominator_ll;
int index = res.length() - 1;
unordered_map<int, int> umap;
while(numerator_ll && umap.count(numerator_ll) == 0){
umap[numerator_ll] = ++index;
numerator_ll = numerator_ll * 10;
res += to_string(numerator_ll / denominator_ll);
numerator_ll = numerator_ll % denominator_ll;
}
if(umap.count(numerator_ll) > 0){
res.insert(umap[numerator_ll], "(");
res += ")";
}
return res;
}
};