leetcode:166. 分数到小数

题目

给定两个整数,分别表示分数的分子 numerator 和分母 denominator,以 字符串形式返回小数
如果小数部分为循环小数,则将循环的部分括在括号内。
如果存在多个答案,只需返回 任意一个
对于所有给定的输入,保证 答案字符串的长度小于 10^4

示例:

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

解答 & 代码

模拟
注意处理负数、整数部分等

  1. class Solution {
  2. public:
  3. string fractionToDecimal(int numerator, int denominator) {
  4. // 哈希表,存储 <余数,出现该余数对应的下标>
  5. unordered_map<int, int> map;
  6. // 得到最终结果的符号位
  7. char sign = '+';
  8. if((numerator > 0 && denominator < 0) || (numerator < 0 && denominator > 0))
  9. sign = '-';
  10. // 将分子、分母都用 long 表示,再变为正数(否则负数变正数可能会溢出)
  11. long numeratorL = numerator;
  12. numeratorL = numeratorL > 0 ? numeratorL : -numeratorL;
  13. long denominatorL = denominator;
  14. denominatorL = denominatorL > 0 ? denominatorL : -denominatorL;
  15. string result = ""; // 结果
  16. if(sign == '-') // 如果结果是负数,则先加上负号
  17. result += '-';
  18. // 先得到结果的整数部分
  19. result += to_string(numeratorL / denominatorL);
  20. // 如果结果就是整数,则直接返回结果
  21. if(numeratorL % denominatorL == 0)
  22. return result;
  23. // 给结果的整数部分后面加上小数点
  24. result.push_back('.');
  25. // 将整数部分除法的余数先存入哈希表,下标存的是小数点的位置
  26. // 因为如果后续这个余数重复,循环小数的左括号加在小数点后面
  27. map[numeratorL % denominatorL] = result.size() - 1;
  28. numeratorL = numeratorL % denominatorL * 10;
  29. int idx = result.size();
  30. int start = -1; // 第一个重复余数的下标,start + 1 是循环小数左括号的位置
  31. int end = -1; // 第一个重复元素第二次出现的下标,end + 2 是循环小数右括号的位置(因为先插入了左括号)
  32. while(true)
  33. {
  34. // 计算当前位的结果
  35. result += numeratorL / denominatorL + '0';
  36. // 如果余数为 0,则结束循环
  37. if(numeratorL % denominatorL == 0)
  38. break;
  39. // 如果当前余数之前出现过,则记录两次出现的位置,并结束循环
  40. if(map.find(numeratorL % denominatorL) != map.end())
  41. {
  42. start = map[numeratorL % denominatorL];
  43. end = idx;
  44. break;
  45. }
  46. else // 否则,将当前的余数及下标存入哈希表
  47. map[numeratorL % denominatorL] = idx;
  48. // 余数乘 10 作为下一轮除法运算的分子
  49. numeratorL = numeratorL % denominatorL * 10;
  50. ++idx;
  51. }
  52. // 如果结果是循环小数,插入左括号和右括号
  53. if(start != -1)
  54. {
  55. result.insert(start + 1, "(");
  56. result.insert(end + 2, ")");
  57. }
  58. return result;
  59. }
  60. };

复杂度分析:

  • 时间复杂度 O():
  • 空间复杂度 O():

执行结果:

  1. 执行结果:通过
  2. 执行用时:0 ms, 在所有 C++ 提交中击败了 100.00% 的用户
  3. 内存消耗:6 MB, 在所有 C++ 提交中击败了 98.80% 的用户