zoukankan      html  css  js  c++  java
  • Leetcode: Fraction to Recurring Decimal

    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)".

    这道题与Divide Two Integer那道题很像,但是却不一样。不一样的原因在于

    1. divide two integer要求的返回的是int值。所以那道题Integer.MIN_VALUE / -1要特殊讨论,返回Integer.MAX_VALUE. (直接除还是会是Integer.MIN_VALUE, 因为b = -a 在计算机内部是 b = ~a + 1 这样处理的)而这道题要求返回的是String, 不用考虑Integer的范围

    2. 虽然divide two Integer和这道题一样,都需要把numerator和denominator转化为long先,但是原因是不一样的。Divide Two Integer是怕移位溢出,因为其中有一步是 while(num >= (den<<i)) { i ++; }。而这道题转换成long是为了Math.abs的时候,不溢出。因为结果是String, 不考虑Integer范围,所以abs(-128)应该return string形式的128。但是如果用Integer, 因为-128~127. Math.abs(-128)会变成128,但是int范围是127.所以会溢出。转换成long这样Math.abs会防止溢出。

    反正注意这两个题目的区别。divide two integer是要求返回的int,有范围要求,这个题目没有,只要求返回结果的string。不需要转换成int范围内的值。

    然后谈谈怎么除得小数的问题,我的想法是double division, 就是像double d = ((double) num) / denom; 这样。可行的方法有:

    double b = ((double)317)/219;
    System.out.println(b);
    double b = 317.0/219;
    System.out.println(b);
    double b = 317d/219d;

    但是这样子是不行的:

    double b = 317/219;
    System.out.println(b);

    这样除完之后,再用Double.toString()把它转化为String再处理无限循环的问题。但是好像那个时候再找是从哪里开始循环的,不太容易。

    于是参考了网上的思路

    核心思想就是:模仿除法的过程,然后用hashmap存储numerator的值,如果出现了相同的numerator那么就出现了cycle,

    利用stringbuilder来append string,hashmap里面 key是numerator,value是stringbuilder.length,这样出现了cycle,知道如何去插入"(",再append")".

    还要记得在第一次除法完成之后,加上小数点,因为第一次除法就可以把整个整数部分全算出来了,接下来小数部分才是一位一位地算

     1         public String fractionToDecimal(int numerator, int denominator) {
     2             long num = (long)numerator;
     3             long den = (long)denominator;
     4             boolean isNeg = false;
     5             if (num < 0) isNeg = !isNeg;
     6             if (den < 0) isNeg = !isNeg;
     7             num = Math.abs(num);
     8             den = Math.abs(den);
     9             HashMap<Long, Integer> dict = new HashMap<Long, Integer>();
    10             StringBuffer res = new StringBuffer();
    11             if (num == 0) return "0";
    12             long digit = num / den; //deal with integer part
    13             res.append(digit);
    14             num = (num % den) * 10;
    15             if (num != 0) res.append("."); //deal with decimal point
    16             else return res.toString();
    17             while (num != 0 && !dict.containsKey(num)) {
    18                 dict.put(num, res.length());
    19                 digit = num / den;
    20                 res.append(digit);
    21                 num = (num % den) * 10;
    22             }
    23             if (dict.containsKey(num)) {
    24                 res.insert(dict.get(num).intValue(), '(');
    25                 res.append(')');
    26             }
    27             if (isNeg) res.insert(0, '-');
    28             return res.toString();
    29         }

    注意第23行Integer要先转换成int。注意一个问题,那就是没有处理这种情况: 20 / 3 = 6.66666, 因为我不知道这样子是写成(6.)呢还是6.(6),我理解应该写成后者,所以整数部分单独考虑且不加入hashmap

  • 相关阅读:
    Redis面试题
    Mysql面试题
    Mybatis面试题
    Springmvc面试题
    spring常见面试题
    优雅的参数校验
    Linux安装mongodb
    Redis缓存的雪崩、穿透、击穿
    语音识别(LSTM+CTC)
    大数据利器Hive
  • 原文地址:https://www.cnblogs.com/EdwardLiu/p/4251895.html
Copyright © 2011-2022 走看看