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.
If multiple answers are possible, return any of them.
It is guaranteed that the length of the answer string is less than 104
for all the given inputs.
Example 1:
Input: numerator = 1, denominator = 2 Output: "0.5"
Example 2:
Input: numerator = 2, denominator = 1 Output: "2"
Example 3:
Input: numerator = 4, denominator = 333 Output: "0.(012)"
Constraints:
-231 <= numerator, denominator <= 231 - 1
denominator != 0
This problem involves converting a fraction (represented by its numerator and denominator) into its decimal representation, handling both terminating and repeating decimals.
Approach:
The solution utilizes a combination of mathematical operations and a hash table (or dictionary in Python) to efficiently detect and represent repeating decimal patterns. Here's a breakdown:
Handle Trivial Cases:
Determine Sign:
Integer Part:
numerator // denominator
in Python, /
in other languages) to get the integer part of the decimal.Remainder:
%
). This remainder is crucial for determining the fractional part.Handle Zero Remainder:
Fractional Part (Repeating Decimal Detection):
Time Complexity: O(l), where l is the length of the resulting decimal string. In the worst case (a long repeating pattern), we might iterate through the algorithm many times. The problem statement guarantees that l < 10^4
.
Space Complexity: O(l) - the hash table stores at most l entries (remainders).
Code Examples (Python and Java):
Python:
class Solution:
def fractionToDecimal(self, numerator: int, denominator: int) -> str:
if numerator == 0:
return "0"
sign = "-" if (numerator > 0) ^ (denominator > 0) else ""
numerator, denominator = abs(numerator), abs(denominator)
integer_part = numerator // denominator
remainder = numerator % denominator
if remainder == 0:
return sign + str(integer_part)
fractional_part = ""
remainder_map = {} # Dictionary to track remainders
index = 0
while remainder != 0 and remainder not in remainder_map:
remainder_map[remainder] = index
remainder *= 10
fractional_part += str(remainder // denominator)
remainder %= denominator
index += 1
if remainder == 0:
return sign + str(integer_part) + "." + fractional_part
else:
repeat_index = remainder_map[remainder]
return sign + str(integer_part) + "." + fractional_part[:repeat_index] + "(" + fractional_part[repeat_index:] + ")"
Java:
import java.util.HashMap;
import java.util.Map;
class Solution {
public String fractionToDecimal(int numerator, int denominator) {
if (numerator == 0) {
return "0";
}
String sign = ((numerator > 0) ^ (denominator > 0)) ? "-" : "";
long num = Math.abs((long) numerator);
long den = Math.abs((long) denominator);
long integerPart = num / den;
long remainder = num % den;
if (remainder == 0) {
return sign + integerPart;
}
StringBuilder fractionalPart = new StringBuilder();
Map<Long, Integer> remainderMap = new HashMap<>();
int index = 0;
while (remainder != 0 && !remainderMap.containsKey(remainder)) {
remainderMap.put(remainder, index);
remainder *= 10;
fractionalPart.append(remainder / den);
remainder %= den;
index++;
}
if (remainder == 0) {
return sign + integerPart + "." + fractionalPart;
} else {
int repeatIndex = remainderMap.get(remainder);
return sign + integerPart + "." + fractionalPart.substring(0, repeatIndex) + "(" + fractionalPart.substring(repeatIndex) + ")";
}
}
}
The other languages (C++, Go, TypeScript, C#) follow similar logic, adapting the data structures and syntax as needed for each language. The core algorithm remains consistent across all implementations.