小数の無限ループが発生するかどうかを判断するには、ループ部分を見つける必要があります。
循環ナックルが発生した場合、すでに出現した後に、被除数を被除数で割った商が、例えば2 / 3で、2が3より小さく、場所を借りて、20 / 3 = 6 ...という状況が発生します。 2、そして商は再び6になり、出現した後に6になるので、サイクリックナックルは6であることがわかります。
最終結果は0。
発生した四則演算を記録するためにはハッシュテーブルが必要で、割り算は全分割が行われるか、円ナックルが発生するまで何度でも繰り返すことができます。
この問題のテストケースでは、分子が-2147483648(-2^31)、分母が-1なので、商は2147483648(2^31)となる可能性があり、intの最大値は2^31-1なので、intが爆発する可能性があるため、中間計算の結果を格納するためにlong longを使用しています。
コードは以下の通り:
class Solution {
public:
string fractionToDecimal(int numerator, int denominator) {
typedef long long LL;
LL x = numerator, y = denominator;
if(x % y == 0) { //除算が行われた場合、その結果を直接返す
return to_string(x / y);
}
string res;
if((x < 0) ^ (y < 0)) { //xとyのどちらか一方だけが負の場合、最終的な商は負となる。
res += '-';
}
x = abs(x), y = abs(y);
res += to_string(x / y) + '.'; //整数部分を計算し、小数点を加えるのを忘れないようにする。
x %= y;
unordered_map<LL, int> hash; //res文字列の現在の商をその位置に記録するハッシュ・テーブル、これは後で重複を判定し、循環ノットを阻止するためである。
while(x != 0) {
hash[x] = res.size(); //この商の現在の位置をresに記録し、後でresの添え字に従って割り込みサイクル部
x *= 10; //除算のルールに従い、除数は被除数より小さく、下位の位を借りる
res += to_string(x / y);
x %= y;
if(hash.count(x) != 0) { //繰り返される商が発生し、ループセクションが見つかったことを示す、ループセクションに括弧を加える
res = res.substr(0, hash[x]) + '(' + res.substr(hash[x]) + ')'; //res.substr(0, hash[x])非周期的な部分と、括弧で囲まれた循環的な部分、これが最終的な答えである。
break;
}
}
return res;
}
};