Leetcode 166. Fraction to Recurring Decimal 弗洛伊德判环
分数转小数,要求输出循环小数 如2 3 输出0.(6)
弗洛伊德判环的原理是在一个圈里,如果一个人的速度是另一个人的两倍,那个人就能追上另一个人。代码中one就是速度1的人,而two就是速度为2的人。
Fraction to Recurring Decimal可以使用弗洛伊德判环,不同的是要找到循环出现的起始点,因此会比单单判断是否循环出现的题要难一点,代码要长一点,但是它比是用map的实现会更快。
要做出这道题有几个注意点:
1)对于整数的求余和整除运算要注意,特别负数的求余运算, 可以参考 getMode_()和getShang_();
2) 由于整数整除的特殊性,对于整数整除是0的无法判断正负,因此要转化成double再判断;
3)对于弗洛伊德判环请注意退出条件和找到循环出现的起始点和结束点,注意初始化。
1 class Solution { 2 public: 3 typedef long long __int64; 4 inline __int64 getShang_(__int64 numerator, __int64 denominator){//特别注意数字都要取绝对值 5 return abs(numerator) / abs(denominator); 6 } 7 8 inline __int64 getMod_(__int64 numerator, __int64 denominator){//特别注意数字都要取绝对值 9 return abs(numerator) % abs(denominator); 10 } 11 12 inline std::string inttostr_(__int64 num){ 13 char t[20] = { 0 }; 14 sprintf(t, "%lld", num); 15 return std::string(t); 16 } 17 18 std::string fractionToDecimal(int numerator, int denominator) { 19 std::string Integer_(""); 20 if ((double)numerator / denominator < 0) Integer_ = "-"; //整数整除是0的无法判断正负 21 Integer_ += inttostr_(getShang_(numerator, denominator)); 22 23 if (0 == getMod_(numerator,denominator) ) { 24 return Integer_; 25 } 26 Integer_ += "."; 27 __int64 tnumerator = numerator; 28 tnumerator = getMod_ (tnumerator, denominator); 29 //printf("%lld\n", numerator); 30 __int64 one = tnumerator; 31 __int64 two = tnumerator; 32 std::vector<__int64> vyushu; 33 std::string Decimal_(""); 34 vyushu.push_back(two); 35 int cnt = 0; //循环节周期 36 while (true) 37 { 38 one = getMod_(one * 10, denominator); 39 40 Decimal_ += inttostr_(getShang_(two * 10, denominator)); 41 two = getMod_(two * 10, denominator); 42 vyushu.push_back(two); 43 if (0 == two) break;//退出条件 44 45 Decimal_ += inttostr_(getShang_(two * 10, denominator)); 46 two = getMod_(two * 10, denominator); 47 vyushu.push_back(two); 48 if (0 == two) break;//退出条件 49 50 cnt++; 51 if (two == one) break; 52 } 53 /*for (auto i:vyushu){ 54 std::cout << i << std::endl; 55 } 56 std::cout << Decimal_ << std::endl; 57 std::cout << cnt << std::endl;*/ 58 if (two){ //找到循环出现的起始点和结束点[j,k) 59 int j = 0, k = 0; 60 for (std::vector<int>::size_type i = vyushu.size()-1; i >= 0&& i>=cnt; --i){ 61 if (vyushu[ i -cnt] != vyushu[ i]){ 62 j = i - cnt + 1; 63 break; 64 } 65 } 66 for (std::vector<int>::size_type i = j + 1; i < vyushu.size(); ++i){ 67 if (vyushu[i] == vyushu[j]) { 68 k = i; 69 break; 70 } 71 } 72 //std::cout << j << " " << k << std::endl; 73 return Integer_ + Decimal_.substr(0, j) + "(" + Decimal_.substr(j, k - j) +")"; 74 } 75 else return Integer_ + Decimal_; 76 77 } 78 };
在代码中注释部分出现的某些代码是来自c++11标准的,请忽略! 另外c++11标准直接支持__int64。