Fork me on GitHub

Fraction to Recurring Decimal

Description

https://leetcode.com/problems/fraction-to-recurring-decimal/description/

Solution

Pay attention to the fact that the pair of quote plus redundant in each divide iteration is the feature to judge whether the loop happened. Based on which, We ssing a list to record the order of the pair list, and maintain a set to judge whether the pair is occupied in each iteration. Once it was in the set, we stop it. Then we traverse the pair list to find the loop part and the unloop part.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
class Pair {
private long quote;
private long remain;
public Pair(long quote, long remain) {
this.quote = quote;
this.remain = remain;
}

public long getQuote() {
return this.quote;
}

public long getRemain() {
return this.remain;
}
@Override
public int hashCode(){
return (int) (this.quote * this.remain);
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if(obj instanceof Pair) {
return ( (Pair)obj ).remain == this.remain && (( (Pair)obj ).getQuote() == this.quote);
}
return false;
}
}


public class Solution {
public String fractionToDecimal(int numerator, int denominator) {
StringBuilder ret = new StringBuilder();
ArrayList<Character> integerList = new ArrayList();
HashSet<Pair> remainQuoteSet = new HashSet<>();
ArrayList<Pair> remainQuoteList = new ArrayList<>();

long longNumerator = (long) numerator;
long longDenominator = (long) denominator;
if (longNumerator*longDenominator < 0) ret.append('-');
longNumerator = Math.abs(longNumerator);
longDenominator = Math.abs(longDenominator);
long quote = longNumerator / longDenominator;
long remain = longNumerator % longDenominator;

//Process Integer
do{
integerList.add( (char) (quote % 10 + '0') );
quote /= 10;
}while(quote > 0);
for (int index = integerList.size()-1; index >= 0; index -= 1){
ret.append(integerList.get(index));
}

if (remain == 0) {
return ret.toString();
}

ret.append(".");

//Process Decimal
quote = remain * 10 / longDenominator;
remain = remain * 10 % longDenominator;
Pair pair = new Pair(quote, remain);
while(remainQuoteSet.contains(pair) == false) {
remainQuoteSet.add(pair);
remainQuoteList.add(pair);
quote = remain * 10 / longDenominator;
remain = remain * 10 % longDenominator;
pair = new Pair(quote, remain);
}

int beginIndexOfLoop = remainQuoteList.indexOf(pair);
//Find the unloop section
for (int index = 0; index < beginIndexOfLoop; index += 1) {
ret.append( (char) (remainQuoteList.get(index).getQuote() + '0') );
}

//Find the loop section
if (remain != 0) {
ret.append('(');
for (int index = beginIndexOfLoop; index < remainQuoteList.size(); index += 1) {
ret.append( (char) (remainQuoteList.get(index).getQuote() + '0') );
}
ret.append(')');
}

System.out.println(remainQuoteList);
return ret.toString();
}
}

Attention

  1. In java, you can use the class as the key word in the map(set), but to make them work functionally, you need some extra effort——override the hashCode and equals methods in the class.
  2. The corner case of big int can reduce to some awkward situation, so my suggestion is convert the parmeter to long type.