LeetCode(166) Fraction to Recurring Decimal

183 篇文章 0 订阅
13 篇文章 0 订阅

题目如下:

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.


分析如下:

对于可以整除的,和对于不可以整除但是算出来的小数不是循环小数的,都可以直接计算结果转化为字符串。
比较麻烦的是循环节的小数。为了找到循环节,可以用hashtable保存每一步余数,如果当前余数和之前某个余数相同,则重复之间的这段发生循环。

这里的我踩过的坑是,为什么hashtable保存的是每次计算的余数,而不是每次计算的商呢?因为小数部分有循环节部分,还有循环节之前的不规律的部分,如果保存商,则可能会把循环节之前的部分错误计算成循环节部分。

更详细的解答直接抄官网。

    0.16  
6 ) 1.00
    0 
    1 0       <-- Remainder=1, mark 1 as seen at position=0.
    - 6 
      40      <-- Remainder=4, mark 4 as seen at position=1.
    - 36 
       4      <-- Remainder=4 was seen before at position=1, so the fractional part which is 16 starts repeating at position=1 => 1(6).

The key insight here is to notice that once the remainder starts repeating, so does the divided result.

You will need a hash table that maps from the remainder to its position of the fractional part. Once you found a repeating remainder, you may enclose the reoccurring fractional part with parentheses by consulting the position from the table.

The remainder could be zero while doing the division. That means there is no repeating fractional part and you should stop right away.

be wary of edge case such as negative fractions and nasty extreme case such as -2147483648 / -1.

更多对于小数的循环节的资料可以看这里

//http://mathforum.org/dr.math/faq/faq.fractions.html
//http://mathforum.org/library/drmath/view/57099.html


我的代码:

//7ms
//hash中存的是余数,不是商。
// 8/2 = 4
// 1/ 8 = 0.125
// 8 / 8 = 1
// 8 / 3 = 2.(6)
// 1 / 3 = 0.(3)
// 11 / 6 = 1.8(3)
// 1 / 7  = 0.(142857)
// 50 / 7  = 7.(142857)
class Solution {
public:
    string fractionToDecimal(int numerator, int denominator) {
        long long l_numerator = numerator;
        long long l_denominator = denominator;
        long long rest = 0;
        
        string result = "";
        unordered_map<long long , int> u_map;
        bool is_positive = true;
        if (l_denominator == 0) return result;
        if (l_numerator == 0) return "0";
        if (l_numerator == INT_MIN && l_denominator == -1) return "2147483648";
        if (l_numerator < 0) {
            is_positive = 1 - is_positive;
            l_numerator = - l_numerator;
        }
        if (l_denominator < 0) {
            is_positive = 1 - is_positive;
            l_denominator = - l_denominator;
        }
        if (l_numerator % l_denominator == 0) {
            result = to_string(l_numerator/l_denominator);
        } else {
            result = to_string(l_numerator / l_denominator) + '.';
        }
        
        rest = l_numerator % l_denominator;
        int index = result.length(); // starting point
        while (rest != 0 && u_map.find(rest) == u_map.end()) {
            u_map[rest] = index;
            rest *= 10;
            //下面的while完全没有必要。
            //while (rest * 10 < l_denominator) {
            //    rest *= 10;
            //    result +="0";
            //    index++;
            //}
            result += to_string(rest / l_denominator);
            rest = rest % l_denominator;
            index++;
        }
        if (rest != 0) {
            result.insert(u_map[rest], 1, '(');
            result.insert(result.length(), 1, ')');
        }
        if (is_positive)
            return result;
        else
            return "-" + result;
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值