1.問題描述
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.
即給定一個分數的分子和分母,返回該分數的小數形式,如果是無限循環小數,則用括號括起來循環部分
如:
Input: numerator = 1, denominator = 2
Output: "0.5"
Input: numerator = 2, denominator = 1
Output: "2"
Input: numerator = 2, denominator = 1
Output: "2"
所給函數框架:
class Solution {
public:
string fractionToDecimal(int numerator, int denominator)
{
}
};
2.解題思路
首先,肯能會進行負數分數,所以爲處理方便先判斷其正負號,然後統一取絕對值進行處理
判斷正負號可以用 用異或 來實現
bool sign = numerator < 0 ^ denominator < 0;
如果兩者均爲正或爲負數,則返回 false;異號則返回true,表示最後結果爲負
然後就是絕對值的處理,這裏有一個容易犯錯的地方,
INT_MIN 在進行絕對值運算後 會超出 int 類型變量的取值範圍,造成溢出錯誤
所以爲方便起見,我們將變量類型轉換爲 long long 型,可以採用 labs(numerator)或 abs((long long) numerator);
而不能直接寫爲 long long n = abs(numerator);因爲此時右邊返回的是 int型,仍然會出現溢出錯誤
下面重點關注的就是如何判斷是否出現無限循環小數,採用的方法是記錄小數位,一旦發現發現小數位開始重複,則會出現無限循環,所以需要記錄該重複小數首次出現的位置;爲了進行查找記錄的方便,所以採用 哈希表
同時,在除法中求小數時用到了一個小技巧,就是 對餘數*10再去除被除數,得到的就是小數位上的數
class Solution {
public:
string fractionToDecimal(int numerator, int denominator)
{
bool sign = numerator < 0 ^ denominator < 0;//按位異或,只有兩者不同號時才爲負,記符合標誌位爲fa
if(numerator == 0)
{
return "0";
}
string res;
long long n = labs(numerator);
long long d = labs(denominator);
res += to_string(n/d);
if(n%d == 0)
{
return sign ? "-" + res : res;
}
else
{
res += ".";
}
unordered_map<int,int> mymap;
for(long long r = n%d; r; r =r%d)
{
if(mymap.count(r) > 0)//即已經出現過該小數,則陷入循環
{
res.insert(mymap[r],1,'(');
res.push_back(')');
break;
}
mymap[r] = res.size();
r *= 10;
res += to_string(r/d);
}
if(sign)
{
res = "-" + res;
}
return res;
}
};