[LeetCode]58. Fraction to Recurring Decimal分数化小数
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)".
Credits:
Special thanks to @Shangrila for adding this problem and creating all test cases.
Subscribe to see which companies asked this question
解法:分数一定可以表示为不循环小数(包括整数)或者无限循环小数。无限不循环小数即是无理数。设置一个哈希表,存储每一次的余数,以及该余数在返回结果result中的下标。每一次得到新的余数,就查询该余数是否已经在哈希表中,是的话说明开始循环了,那么直接在result中该余数对应的位置后面插入‘(’,result末尾加上‘)’,结束运算。如果在哈希表中没找到,则继续正常运算。注意不能根据某一个商的循环来判断循环节是否完成,比如1/17=0.(05882352941176470),8就出现了两次,但是结果却不是0.5(8);Hash表设计为<rem, index>是为了方便找到循环节后左括号的插入。
class Solution { public: string fractionToDecimal(int numerator, int denominator) { //防止INT_MIN取绝对值超出范围 long long num = numerator, den = denominator; if (den == 0) return ""; bool isNegative = (num > 0 && den < 0) || (num < 0 && den > 0); num = num > 0 ? num : -num; den = den > 0 ? den : -den; // 整数部分 string res = ""; res += (isNegative ? "-" : "") + to_string(num / den); long long rem = num % den; //注意极小数除以极大数时余数可能超出int范围 if (rem == 0) return res; else res += "."; // 小数部分 unordered_map<int, int> m; while (rem != 0) { if (m.find(rem) != m.end()) { res.insert(m[rem], 1, '('); res += ")"; break; } m[rem] = res.size(); // 方便插入左括号 rem *= 10; res += to_string(rem / den); rem %= den; } return res; } };
小数转分数:不循环小数转分数很简单,乘以10的幂将小数部分去掉即可;无限循环小数转分数分两种:一是循环节从小数点后第一位开始的,比如0.333(3/9-->1/3)...、0.7272(72/99-->8/11)...,循环节当做分子,循环节有几位就拿几个9当做分母再约分即可;另一种循环节不从小数点后第一位开始,比如0.437272...,乘以100得到43.7272...,可以理解为43+8/11即481/11,前面乘了100因此再除以100,即是481/1100。