ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Leetcode 166、分数到小数

2021-10-03 20:31:26  阅读:290  来源: 互联网

标签:denominatorLL denominator numerator ans 余数 166 Leetcode 小数


Problem Source : https://leetcode-cn.com/problems/fraction-to-recurring-decimal/

Solution Source : https://github.com/hujingbo98/algorithm/blob/master/source/leetcode/0166_FractionToRecurringDecimal.cpp

166、分数到小数

给定两个整数,分别表示分数的分子 numerator 和分母 denominator,以字符串形式返回小数。

如果小数部分为循环小数,则将循环的部分括在括号内。
如果存在多个答案,只需返回任意一个 。
对于所有给定的输入,保证答案字符串的长度小于 10^4。

示例 1:

输入:numerator = 1, denominator = 2
输出:"0.5"

示例 2:

输入:numerator = 2, denominator = 1
输出:"2"

示例 3:

输入:numerator = 2, denominator = 3
输出:"0.(6)"

示例 4:

输入:numerator = 4, denominator = 333
输出:"0.(012)"

示例 5:

输入:numerator = 1, denominator = 5
输出:"0.2"

提示:

-2^31 <= numerator, denominator <= 2^31 - 1
denominator != 0

方法一:长除法 + 哈希表

将分数转换成整数或小数,做法是计算分子和分母相除的结果。可能的结果有三种,整数、有限小数、无限循环小数。

如果分子可以被分母整除,则结果是整数,将分子除以分母的商以字符串形式返回即可。

如果分子不能被分母整除,则结果是有限小数或无限循环小数,需要通过模拟长除法的方式计算结果。为了方便处理,首先根据分子和分母的正负确定答案的正负(注意此时分子和分母都不为 0),然后将分子和分母都转成正数,再计算长除法。

计算长除法时,首先计算结果的整数部分,将以下部分拼接到结果中:

  1. 如果结果是负数则将负号拼接到结果中,如果结果是正数则跳过这一步。
  2. 将整数部分拼接到结果中。
  3. 将小数点拼接到结果中。

完成上述拼接之后,根据余数计算小数部分。

计算小数部分时,每次将余数乘以 10,然后计算小数的下一位数字,并得到新的余数。重复上述操作知道余数为 0 或找到循环节。

  • 如果余数为 0,则结果是有限小数。
  • 如果找到循环节,则在循环节的开始位置和结束位置插入括号。

如何找到循环节? 对于相同的余数,得到的小数的下一位数字一定是相同的,因此如果计算过程中发现某一位的余数在之前已经出现过,则为找到循环节。为了记录每个余数是否出现过,需要使用哈希表存储每个余数在小数部分第一次出现的下标。

在每次得到余数时,判断该余数之前是否出现过,如果出现过则在第一次出现的位置加上左括号,在末尾加上右括号返回即可。

时间复杂度是 O(k),其中 k 是结果字符串的长度,该题中 k <= 10^4。

空间复杂度是 O(k)。主要是哈希表所用的空间,哈希表最多存 10^4 个键值对。

string fractionToDecimal(int numerator, int denominator) {
    string ans;
    long long numeratorLL = numerator;
    long long denominatorLL = denominator;

    if (0 == numeratorLL % denominatorLL)
        return to_string(numeratorLL / denominatorLL);

    if ((numeratorLL < 0) ^ (denominatorLL < 0))
        ans.push_back('-');
    numeratorLL = abs(numeratorLL);
    denominatorLL = abs(denominatorLL);

    int nbit = numeratorLL / denominatorLL;
    ans.append(to_string(nbit));
    long long nextNumeratorLL = numeratorLL % denominatorLL * 10;
    ans.push_back('.');

    unordered_map<long long, int> cache;
    while (ans.length() < 10000 && 0 != nextNumeratorLL) {
        auto it = cache.find(nextNumeratorLL);
        if (it == cache.end()) {
            cache.insert(std::pair(nextNumeratorLL, ans.length()));
        } else {
            ans.insert(it->second, 1, '(');
            ans.push_back(')');
            break;
        }
        nbit = nextNumeratorLL / denominatorLL;
        ans.append(to_string(nbit));
        nextNumeratorLL = nextNumeratorLL % denominatorLL * 10;
    }
    return ans;
}

标签:denominatorLL,denominator,numerator,ans,余数,166,Leetcode,小数
来源: https://blog.csdn.net/weixin_44537961/article/details/120598070

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有