题目:
我采用模拟的方法,拼尽全力终于战胜,特殊情况太多了,最好是用 gdb 一次次调试发现代码中没有考虑到的地方再完善。
注意不要先除以最大公因数,因为最大公因数的计算时间复杂度要高于长除法。
此外最好先计算整数部分,再计算小数部分,我的这个解法没有考虑这个导致代码有点复杂。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
| #include <numeric> #include <string> #include <unordered_map> #include <vector>
using std::string; using std::unordered_map; using std::vector;
class Solution { public: string fractionToDecimal(int numerator, int denominator) {
unsigned long long dividend; unsigned long long divisor; unsigned long long quotient; unsigned long long reminder; int dot = -1; int bracket = -1; vector<int> res_vec; vector<int> numerator_vec; unordered_map<unsigned long long, unsigned long long> div_map; string res; int i = 0; int n; bool negative = false;
if (numerator == 0) { return "0"; } if ((numerator < 0 && denominator > 0) || (numerator > 0 && denominator < 0)) { negative = true; } dividend = std::llabs((long long)numerator); divisor = std::llabs((long long)denominator);
while (dividend != 0) { numerator_vec.insert(numerator_vec.begin(), dividend % 10); dividend /= 10; } dividend = 0;
n = numerator_vec.size(); while (i < n && dividend < divisor) { dividend = dividend * 10 + numerator_vec[i]; i++; }
do { if (div_map.find(dividend) != div_map.end() && dot > 0) { bracket = div_map[dividend]; break; } else { div_map[dividend] = res_vec.size(); } quotient = dividend / divisor; reminder = dividend % divisor; res_vec.push_back(quotient);
if (i < numerator_vec.size()) { dividend = reminder * 10 + numerator_vec[i]; i++; reminder = 1; } else { dividend = reminder * 10; if (dot < 0) dot = res_vec.size(); }
} while (reminder != 0);
if (bracket >= 0 && dot > 0 && bracket < dot) { n = dot - bracket; for (i = 0; i < n; i++) { res_vec.push_back(res_vec[i + bracket]); } bracket = dot; }
n = res_vec.size(); if (negative) { res += '-'; }
for (i = 0; i < n; i++) { if (i == dot) { res += '.'; } if (i == bracket) { res += '('; }
res += '0' + res_vec[i]; }
if (bracket > 0) { res += ')'; }
return res; } };
int main() { Solution s; printf("%s\n", s.fractionToDecimal(420, 226).c_str()); printf("%s\n", s.fractionToDecimal(-22, -2).c_str()); printf("%s\n", s.fractionToDecimal(500, 10).c_str()); printf("%s\n", s.fractionToDecimal(4, 333).c_str()); printf("%s\n", s.fractionToDecimal(50, 8).c_str()); }
|
官方方法也是模拟长除法,但不同的是我是记录了被除数,这个解法记录的是余数从而判断是否产生了循环小数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| class Solution { public: string fractionToDecimal(int numerator, int denominator) { long numeratorLong = numerator; long denominatorLong = denominator; if (numeratorLong % denominatorLong == 0) { return to_string(numeratorLong / denominatorLong); }
string ans; if (numeratorLong < 0 ^ denominatorLong < 0) { ans.push_back('-'); }
numeratorLong = abs(numeratorLong); denominatorLong = abs(denominatorLong); long integerPart = numeratorLong / denominatorLong; ans += to_string(integerPart); ans.push_back('.');
string fractionPart; unordered_map<long, int> remainderIndexMap; long remainder = numeratorLong % denominatorLong; int index = 0; while (remainder != 0 && !remainderIndexMap.count(remainder)) { remainderIndexMap[remainder] = index; remainder *= 10; fractionPart += to_string(remainder / denominatorLong); remainder %= denominatorLong; index++; } if (remainder != 0) { int insertIndex = remainderIndexMap[remainder]; fractionPart = fractionPart.substr(0,insertIndex) + '(' + fractionPart.substr(insertIndex); fractionPart.push_back(')'); } ans += fractionPart;
return ans; } };
|