問題
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.
例子
- Given numerator = 1, denominator = 2, return "0.5".
- Given numerator = 2, denominator = 1, return "2".
- Given numerator = 2, denominator = 3, return "0.(6)".
分析
模擬除法的運算過程。設numerator = 10, denominator = 6.
- numerator = 10, denominator = 6, quotient = 1, remander = 4, res = "1.";
- numerator = remander * 10 = 40, denominator = 6, quotient = 6, remander = 4, res = "1.6";
- numerator = remander * 10 = 40, denominator = 6, quotient = 6, remander = 4, res = "1.66".
到第三步可以發現,以后每一步remander都是4,quotient都是6,即開始循環。res應該為"1.(6)".
所以我們要模擬上面的運算,直到remander開始重復某一數字,設該數字為R。用一個map來保存remander和它出現的位置。在remander第一次出現R的位置插入'(',在最后的位置插入')'。
除此之外,還有考慮一下幾點:
- numerator和denominator異號時,在res前加'-';
- quotient和remander要定義成long long,防止溢出,例如numerator = -2147483648, denominator = -1;
- 求int的絕對值時,有溢出的風險,需要先把int轉換成long long.
要點
- 理解小數循環節的含義,能夠模擬除法運算:不斷用余數乘10除以除數,直到余數為0。當余數開始出現重復數字時,商的小數開始循環;
- 注意數值類型的溢出問題;
- string關于char的構造函數為string(size_t n, char c).
時間復雜度
O(n), n位數字的長度
空間復雜度
O(n)
代碼
class Solution {
public:
string fractionToDecimal(int numerator, int denominator) {
if (numerator == 0) return "0";
string res;
if (numerator < 0 ^ denominator < 0)
res += '-';
long long numer = abs((long long)numerator);
long long denom = abs((long long)denominator);
long long quotient = numer / denom;
long long remander = numer % denom;
res += to_string(quotient);
if (remander == 0) return res;
res += '.';
unordered_map<long long, int> map;
while (remander) {
quotient = remander * 10 / denom;
if (map.find(remander) != map.end()) {
res.insert(map[remander], 1, '(');
res += ')';
break;
}
map[remander] = res.size();
res += to_string(quotient);
remander = remander * 10 % denom;
}
return res;
}
};