1. 程式人生 > >[LeetCode] Fraction to Recurring Decimal 分數轉迴圈小數

[LeetCode] 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.

這道題還是比較有意思的,開始還擔心萬一結果是無限不迴圈小數怎麼辦,百度之後才發現原來可以寫成分數的都是有理數,而有理數要麼是有限的,要麼是無限迴圈小數,無限不迴圈的叫無理數,例如圓周率pi或自然數e等,小學數學沒學好,汗!由於還存在正負情況,處理方式是按正數處理,符號最後在判斷,那麼我們需要把除數和被除數取絕對值,那麼問題就來了:由於整型數INT的取值範圍是-2147483648~2147483647,而對-2147483648取絕對值就會超出範圍,所以我們需要先轉為long long型再取絕對值。那麼怎麼樣找迴圈呢,肯定是再得到一個數字後要看看之前有沒有出現這個數。為了節省搜尋時間,我們採用雜湊表來存數每個小數位上的數字。還有一個小技巧,由於我們要算出小數每一位,採取的方法是每次把餘數乘10,再除以除數,得到的商即為小數的下一位數字。等到新算出來的數字在之前出現過,則在迴圈開始出加左括號,結束處加右括號。程式碼如下:

class Solution {
public:
    string fractionToDecimal(int numerator, int denominator) {
        int s1 = numerator >= 0 ? 1 : -1;
        int s2 = denominator >= 0 ? 1 : -1;
        long long num = abs( (long long)numerator );
        long long den = abs( (long long)denominator );
        
long long out = num / den; long long rem = num % den; unordered_map<long long, int> m; string res = to_string(out); if (s1 * s2 == -1 && (out > 0 || rem > 0)) res = "-" + res; if (rem == 0) return res; res += "."; string s = ""; int pos = 0; while (rem != 0) { if (m.find(rem) != m.end()) { s.insert(m[rem], "("); s += ")"; return res + s; } m[rem] = pos; s += to_string((rem * 10) / den); rem = (rem * 10) % den; ++pos; } return res + s; } };