LeetCode第166题_分数到小数

LeetCode 第166题:分数到小数

题目描述

给定两个整数,分别表示分数的分子 numerator 和分母 denominator,以 字符串形式返回小数

如果小数部分为循环小数,则将循环的部分括在括号内。

如果存在多个答案,只需返回 任意一个

对于所有给定的输入,保证 答案字符串的长度小于 10^4

难度

中等

题目链接

点击在LeetCode中查看题目

示例

示例 1:

输入:numerator = 1, denominator = 2
输出:"0.5"

示例 2:

输入:numerator = 2, denominator = 1
输出:"2"

示例 3:

输入:numerator = 2, denominator = 3
输出:"0.(6)"

示例 4:

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

示例 5:

输入:numerator = 1, denominator = 5
输出:"0.2"

提示

  • -2^31 <= numerator, denominator <= 2^31 - 1
  • denominator != 0

解题思路

方法:模拟长除法

模拟长除法的计算过程,找出循环小数的部分。关键是要记录每次除法的余数及其对应的位置,当出现重复的余数时,就找到了循环节的起始位置。
关键点:

  1. 处理正负号
  2. 处理整数部分
  3. 使用哈希表记录每个余数及其在小数点后的位置
  4. 当余数为0时,表示除尽,不是循环小数
  5. 当出现重复的余数时,找到循环节的起始位置,用括号括起循环部分

时间复杂度:O(l),其中l是结果字符串的长度。
空间复杂度:O(l),需要存储中间余数及其位置。

代码实现

C# 实现

public class Solution {
    public string FractionToDecimal(int numerator, int denominator) {
        if (numerator == 0) return "0";
        
        StringBuilder result = new StringBuilder();
        
        // 处理正负号
        if ((numerator < 0) ^ (denominator < 0)) {
            result.Append("-");
        }
        
        // 转换为long防止溢出
        long num = Math.Abs((long)numerator);
        long den = Math.Abs((long)denominator);
        
        // 整数部分
        result.Append(num / den);
        
        // 小数部分
        long remainder = num % den;
        if (remainder == 0) {
            return result.ToString();
        }
        
        result.Append(".");
        
        // 记录每个余数出现的位置
        Dictionary<long, int> map = new Dictionary<long, int>();
        
        while (remainder != 0) {
            if (map.ContainsKey(remainder)) {
                // 找到循环节,插入左括号
                result.Insert(map[remainder], "(");
                result.Append(")");
                break;
            }
            
            // 记录当前余数的位置
            map[remainder] = result.Length;
            
            remainder *= 10;
            result.Append(remainder / den);
            remainder %= den;
        }
        
        return result.ToString();
    }
}

Python 实现

class Solution:
    def fractionToDecimal(self, numerator: int, denominator: int) -> str:
        if numerator == 0:
            return "0"
        
        result = []
        
        # 处理正负号
        if (numerator < 0) ^ (denominator < 0):
            result.append("-")
        
        # 转换为绝对值
        num = abs(numerator)
        den = abs(denominator)
        
        # 整数部分
        result.append(str(num // den))
        
        # 小数部分
        remainder = num % den
        if remainder == 0:
            return "".join(result)
        
        result.append(".")
        
        # 记录每个余数出现的位置
        remainder_map = {}
        
        while remainder != 0:
            if remainder in remainder_map:
                # 找到循环节,插入左括号
                result.insert(remainder_map[remainder], "(")
                result.append(")")
                break
            
            # 记录当前余数的位置
            remainder_map[remainder] = len(result)
            
            remainder *= 10
            result.append(str(remainder // den))
            remainder %= den
        
        return "".join(result)

C++ 实现

class Solution {
public:
    string fractionToDecimal(int numerator, int denominator) {
        if (numerator == 0) return "0";
        
        string result;
        
        // 处理正负号
        if ((numerator < 0) ^ (denominator < 0)) {
            result += "-";
        }
        
        // 转换为long防止溢出
        long long num = abs((long long)numerator);
        long long den = abs((long long)denominator);
        
        // 整数部分
        result += to_string(num / den);
        
        // 小数部分
        long long remainder = num % den;
        if (remainder == 0) {
            return result;
        }
        
        result += ".";
        
        // 记录每个余数出现的位置
        unordered_map<long long, int> remainderMap;
        
        while (remainder != 0) {
            if (remainderMap.find(remainder) != remainderMap.end()) {
                // 找到循环节,插入左括号
                result.insert(remainderMap[remainder], "(");
                result += ")";
                break;
            }
            
            // 记录当前余数的位置
            remainderMap[remainder] = result.size();
            
            remainder *= 10;
            result += to_string(remainder / den);
            remainder %= den;
        }
        
        return result;
    }
};

性能分析

各语言实现的性能对比:

实现语言执行用时内存消耗特点
C#84 ms36.4 MB实现简洁,性能适中
Python36 ms15.1 MB代码最简洁
C++4 ms6.4 MB性能最优

补充说明

代码亮点

  1. 使用长除法模拟小数计算过程
  2. 使用哈希表记录余数出现的位置,快速找到循环节
  3. 处理了各种边界情况,如符号、整数部分、除尽等

常见错误

  1. 没有考虑数值溢出的情况
  2. 没有处理正负号
  3. 没有正确找到循环小数的开始位置

相关题目

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值