leetcode 166: Fraction to Recurring Decimal


leetcode 166: Fraction to Recurring Decimal - 西施豆腐渣 - 博客频道 - CSDN.NET
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)".
Input : Numerator = 50, Denominator = 22
Output : Recurring sequence is 27
Explanation : 50/22 = 2.272727272..... 
[分析]
1、负数的处理2、INT_MIN的处理,将INT_MIN转化为正数会溢出
我们可以设置一个哈希表,存储每一次的余数,以及该余数在返回结果result中的下标。每一次得到新的余数,就查询该余数是否已经在哈希表中,是的话说明开始循环了,那么直接在result中该余数对应的位置后面插入‘(’,result末尾加上‘)’,结束运算。如果在哈希表中没找到,则继续正常运运算。
关键是确定发生循环的位置, 使用map存所有余数, 当余数已经出现过时, 即发生了循环.
[注意]
Overflow, 符号的处理, 分开两个函数, 使代码更容易读
  1.    public String fractionToDecimal(int numerator, int denominator) {  
  2.           
  3.         long num = numerator;  
  4.         long den = denominator;  
  5.         boolean neg = num * den < 0;  
  6.         num = Math.abs(num);  
  7.         den = Math.abs(den);  
  8.   
  9.         String res = neg ? "-" + Long.toString(num/den) : Long.toString(num/den);  
  10.         long remainder = num%den;  
  11.           
  12.         return (remainder==0) ? res : (res + "." + getDec(remainder, den));          
  13.     } 
  14.     private StringBuilder getDec(long remainder, long den) {  
  15.         Map<Long, Integer> map = new HashMap<Long, Integer>();  
  16.         int i=0;  
  17.         StringBuilder sb = new StringBuilder();  
  18.         while(remainder!=0 && !map.containsKey(remainder)) {  
  19.             map.put(remainder, i);  
  20.             ++i;  
  21.             remainder *= 10;  
  22.             sb.append(Long.toString(remainder/den));  
  23.             remainder %= den;  
  24.         }  
  25.           
  26.         if(remainder!=0){  
  27.             sb.insert((int)map.get(remainder), '(');  
  28.             sb.append(')');  
  29.         }  
  30.         return sb;  
  31.     } 
https://leetcode.com/discuss/31521/short-java-solution
https://leetcode.com/discuss/77994/simple-and-short-solution-in-java
public String fractionToDecimal(int numerator, int denominator) { if (denominator == 0) return ""; StringBuilder str = new StringBuilder(); HashMap<Long, Integer> map = new HashMap<Long, Integer>(); if (numerator < 0 && denominator > 0 || numerator > 0 && denominator < 0) { str.append('-'); } long num = Math.abs((long)numerator); long den = Math.abs((long)denominator); long n = num/den; long reminder = num % den; str.append(n); if (reminder == 0) return str.toString(); else str.append('.'); while(!map.containsKey(reminder)) { map.put(reminder,str.length()); n = reminder*10/den; reminder = reminder*10%den; if (reminder != 0 || reminder == 0 && !map.containsKey(reminder)) { str.append(n); } } if (reminder != 0) { str.insert(map.get(reminder),"("); str.append(')'); } return str.toString(); }
https://leetcode.com/discuss/23079/my-clean-java-solution
public String fractionToDecimal(int numerator, int denominator) { if (numerator == 0) { return "0"; } StringBuilder res = new StringBuilder(); // "+" or "-" res.append(((numerator > 0) ^ (denominator > 0)) ? "-" : ""); long num = Math.abs((long)numerator); long den = Math.abs((long)denominator); // integral part res.append(num / den); num %= den; if (num == 0) { return res.toString(); } // fractional part res.append("."); HashMap<Long, Integer> map = new HashMap<Long, Integer>(); map.put(num, res.length()); while (num != 0) { num *= 10; res.append(num / den); num %= den; if (map.containsKey(num)) { int index = map.get(num); res.insert(index, "("); res.append(")"); break; } else { map.put(num, res.length()); } } return res.toString(); }
http://blog.csdn.net/ljiabin/article/details/42025037
    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.
Just like the question Divide Two Integers, be wary of edge case such as negative fractions and nasty extreme case such as -2147483648 / -1.
难点:如何识别循环体?
解决方法:用一个HashMap记录每一个余数,当出现重复的余数时,那么将会进入循环,两个重复余数之间的部分就是循环体。
示例:1/13=0.076923076923076923...,当小数部分第二次出现0时,就意味着开始了循环,那么需要把076923用括号括起来,结果为0.(076923)。
涉及技巧:1)在不断相除的过程中,把余数乘以10再进行下一次相除,保证一直是整数相除;2)HashMap的key和value分别是<当前余数, 对应结果下标>,这样获取076923时就可根据value值来找。
注意点1:考虑正负数,先判断符号,然后都转化为正数;
注意点2:考虑溢出,如果输入为Integer.MIN_VALUE,取绝对值后会溢出。
Java编程误区:一定要先把 int 转为 long,然后再取绝对值。如果写成 long num = Math.abs(numerator) 就会有问题,因为这句代码在 numerator=Integer.MIN_VALUE 时相当于 long num = Math.abs(-2147483648),这样得到的 num还是 -2147483648。
https://segmentfault.com/a/1190000003794677
整数部分很好处理,只要注意正负号的区分就行了,但是如何处理小数部分呢。如果只是简单的除法,那我们每次把余数乘以10,再除以被除数就可以得到当前位的小数了,得到新的余数,直到余数为0。难点在于,对于无尽循环小数,我们一直这么做永远也不能让余数变为0。这里我们可以用一个哈希表记录每次的余数,如果余数出现重复的时候,说明就产生循环了。为了能找出小数中循环的部分,我们在用哈希表时,还要把每个余数对应的小数位记录下来,这样子我们一旦遇到重复,就知道是从哪里开始循环的。
如果输入的被除数很大,那么余数乘以10有可能溢出,所以我们用long来保存numerator和denominator。
    public String fractionToDecimal(int numerator, int denominator) {
        long num = numerator;
        long den = denominator;
        if(num == 0 || den == 0){
            return "0";
        }
        // 判断结果正负号
        boolean negative = (num > 0 && den < 0) || (num < 0 && den > 0);
        num = Math.abs(num);
        den = Math.abs(den);
        // 得到整数部分
        String integ = (negative ? "-" : "") + String.valueOf(num / den);
        // 如果存在小数部分
        if(num % den != 0){
            num = num % den;
            HashMap<Long, Integer> map = new HashMap<Long, Integer>();
            int pos = 0;
            map.put(num, pos);
            StringBuilder frac = new StringBuilder();
            // 计算小数部分
            while(num != 0){
                // 先把算出的小数加上,再判断余数是否重复,如果余数重复的话,小数会从下一个开始重复
                num = num * 10;
                frac.append(num / den);
                num = num % den;
                // 如果该余数之前出现过,说明有循环,上次出现的位置到当前位置就是循环的部分
                if(map.containsKey(num)){
                    // 将非循环部分和循环部分分开
                    String pre = frac.substring(0, map.get(num));
                    String loop = frac.substring(map.get(num));
                    // 返回有循环的结果
                    return integ + "." + pre + "(" + loop + ")";
                }
                pos++;
                // 记录下当前余数和他对应小数的位置
                map.put(num, pos);
            }
            // 返回无循环有小数的结果
            return integ + "." + frac.toString();
        }
        // 返回无小数的结果
        return integ;
    }
http://yuanhsh.iteye.com/blog/2176178
  1. public String fractionToDecimal(int numerator, int denominator) {  
  2.     if(denominator == 0return "NaN"//特殊情况1  
  3.     if(numerator == 0return "0";  //特殊情况2  
  4.     // 如果两个数符号不同,结果为负数  
  5.     String sign = (denominator>>>31^numerator>>>31) == 1 ? "-" : "";  
  6.       
  7.     // 先把除数和被除数转为long,以免除法和绝对值运算的时候溢出  
  8.     // 比如 -2147483648/-1 = -2147483648, abs(-2147483648) = -2147483648  
  9.     long num = numerator, den = denominator;  
  10.     num = Math.abs(num);  
  11.     den = Math.abs(den);  
  12.     long major = num / den;  
  13.     long rem = num % den;  
  14.     if(rem == 0return sign+major;  
  15.       
  16.     StringBuilder ans = new StringBuilder(sign + major + '.');  
  17.     Map<Long, Integer> map = new HashMap<Long, Integer>();  
  18.     while(rem != 0) {   
  19.         // 如果余数已经出现过一次,那么循环要开始了  
  20.         if(map.containsKey(rem)) {  
  21.             int index = map.get(rem);  
  22.             ans.insert(index, '(').append(')');  
  23.             break;  
  24.         } else {  
  25.             ans.append(rem * 10 / den);  
  26.             map.put(rem, ans.length()-1);  
  27.         }  
  28.         rem = rem * 10 % den;  
  29.     }  
  30.       
  31.     return ans.toString();  
  32. }  
我们还可以通过LinkedHashSet来做。
  1. public  String fractionToDecimal(int numerator, int denominator) {  
  2.     if(denominator == 0return "NaN";   
  3.     if(numerator == 0return "0";    
  4.     String sign = (numerator>>>31^denominator>>>31) == 1 ? "-" : "";  
  5.     long a = numerator, b = denominator;  
  6.     a = Math.abs(a);  
  7.     b = Math.abs(b);  
  8.     String part1 = a / b + "";  
  9.     long mod = a % b;  
  10.     if(mod == 0return sign+part1;  
  11.     long remain = mod;  
  12.       
  13.     Set<Long> s = new LinkedHashSet<>();  
  14.     while (!s.contains(mod) && mod != 0) {  
  15.         s.add(mod);  
  16.         mod = (mod * 10) % b;  
  17.     }  
  18.       
  19.     String part2 = "";  
  20.     boolean repeated = false;  
  21.     for (long i : s) {  
  22.         if (i == mod) {  
  23.             part2 += "(";  
  24.             repeated = true;  
  25.         }  
  26.         part2 += (remain * 10) / b;  
  27.         remain = (remain * 10) % b;  
  28.     }  
  29.     //  if (mod == 0)  
  30.     //      part2 += "(0";  
  31.     if(repeated) {  
  32.         part2 += ")";  
  33.     }  
  34.       
  35.     return sign + part1 + "." + part2;  
  36. }  

http://buttercola.blogspot.com/2015/08/leetcode-fraction-to-recurring-decimal.html
        if (denominator == 0) {
            return "inf";
        }
         
        if (numerator == 0) {
            return "0";
        }
         
        String result = "";
        boolean neg = false;
         
        // Chceck if any negative number
        if ((numerator < 0) ^ (denominator < 0)) {
            neg = true;
        }
 6         if (numerator<0 ^ denominator<0)
 7             res = "-"; 
http://zwzbill8.blogspot.com/2015/05/leetcode-fraction-to-recurring-decimal.html
        int n = numerator;
        int d = denominator;
        if (n == Integer.MIN_VALUE) {
            String s = n + "";
            if (d == 1) return s;
            if (d == -1) return s.substring(1);
        }
        if (1.0 * n / d < 0) {
            return "-" + fractionToDecimal(-n, d);
        }
https://leetcode.com/discuss/20515/my-java-solution
public static String fractionToDecimal(int numerator, int denominator) { String res = ""; long a = Math.abs((long) numerator); long b = Math.abs((long) denominator); if ((denominator < 0 && numerator > 0) || (denominator > 0 && numerator < 0)) { res += "-"; } long intPart= a / b; res += intPart; if (a % b == 0) { return res; } res += "."; long remainder = a % b; HashMap<Long, Integer> map = new HashMap<Long, Integer>(); int i = 1; map.put(remainder, 1); Queue<Long> queue = new LinkedList<Long>(); int begin = -1; while (remainder != 0) { i++; long tmp = remainder * 10 / b; remainder = remainder * 10 % b; if (map.containsKey(remainder)) { begin = map.get(remainder); queue.offer(tmp); break; } else { map.put(remainder, i); queue.offer(tmp); } } if (remainder == 0) { while (!queue.isEmpty()) { res += queue.poll(); } } else { int j = 1; while (!queue.isEmpty()) { long cur = queue.poll(); if (j != begin) { res += cur; } else { res = res + "(" + cur; } j++; } res += ")"; } return res; }
http://bookshadow.com/weblog/2014/12/17/leetcode-fraction-recurring-decimal/
C++ version: http://www.cnblogs.com/higerzhang/p/4177355.html
http://blog.csdn.net/u012162613/article/details/41998617

Divide number and return result in form of a string. e.g 100/3 result should be 33.(3) Here 3 is in brackets because it gets repeated continuously and 5/10 should be 0.5.
Read full article from leetcode 166: Fraction to Recurring Decimal - 西施豆腐渣 - 博客频道 - CSDN.NET

Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts