LeetCode第166题—分数到小数——Python实现

Posted StriveZs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode第166题—分数到小数——Python实现相关的知识,希望对你有一定的参考价值。

LeetCode第166题—分数到小数

自己代码的开源仓库:click here 欢迎Star和Fork 😃

好久没更新了 忙于科研来着 害 都是为了毕业。最近又把自己的事情捡起来了。

题目描述

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

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

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

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

示例 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"

提示:

-231 <= numerator, denominator <= 231 - 1
denominator != 0

代码

思路: 就是模拟大数除法的过程,结合上队列来实现重复被除数查询,从而实现括号的添加。特别注意负数和整除的情况

代码如下:(其中第一个想法是只针对比较单一的情况)

#
# @lc app=leetcode.cn id=166 lang=python
#
# [166] 分数到小数
#

# @lc code=start
import re
import math

class Solution(object):
    def fractionToDecimal(self, numerator, denominator):
        """
        除法运算, 实质为:寻找重复位数
        分两种情况来进行判断:
            1. 直接整除的情况,直接转换为小数就可以了
            2. 不能整除,小数部分为循环小数的情况。
        整体做法均为要用代码实现出发运算过程,包括借位等操作
        针对循环小数的情况:
            1. 最简单的就是2/3 4/3等这种单位循环的小数 0.(6) 1.(6)等等 这种通过下面Version1的代码就可以实现(只需要判断当前被除数和上个被除数是否相同即可了)
            但是这个不适用于4/333的情况,因为它是多位小数循环的情况,单凭上面的思路无法实现
            2. 因此我考虑了新的方法,建立一个队列存储生成的被除数,只要在点了小数点之后就是将所有的被除数存储,然后累积存储被除数直到重复,则将对应重复被除数之间的所有小数点位数用括号括起来
        :type numerator: int
        :type denominator: int
        :rtype: str
        """
        # 判断是否能够整除
        if numerator % denominator == 0:
            return str(numerator / denominator)
        # 思路一
        ## 模拟除法运算
        '''
        res = '' # 保存结果
        flag = True # 标志着重复 被除数连着两次重复
        flag1 = False # 标志小数点使用了
        pre_div = numerator # 存储上一个被除数 当上一个被除数和当前被除数
        trade = 0 # 商
        while flag:
            trade = int(numerator / denominator)
            if trade == 0:
                if res == '': # 单独处理2/3商为0的情况
                    res = '0'
                    res += '.'
                    flag1 = True
                else:
                    #res += str(trade)
                    if '.' not in res:
                        res += '.'
                        flag1 = True
                pre_div = numerator
                numerator = numerator * 10 - trade * denominator
            else:
                res += str(trade)
                pre_div = numerator
                numerator = numerator - trade * denominator
                if flag1:
                    numerator = numerator * 10
            if pre_div == numerator:
                res = res[:-1] + '(' + res[-1] + ')'
                break
            if numerator == 0:
                break
        return res
        '''

        # 思路二
        ## 模拟除法运算+被除数队列记忆
        # 负数处理
        flag2 = False # 负数标志
        if numerator < 0 and denominator < 0:
            numerator = abs(numerator)
            denominator = abs(denominator)
        elif numerator < 0:
            numerator = abs(numerator)
            flag2 = True
        elif denominator < 0:
            denominator = abs(denominator)
            flag2 = True
        res = '' # 结果保存
        flag = True # 标志是否结束
        flag1 = False # 标志小数点使用了
        numerator_list = [] # 存储被除数的list
        trade = 0 # 商
        while flag:
            trade = int(numerator / denominator)
            if trade == 0:
                if res == '': # 单独处理2/3商为0的情况
                    res = '0'
                    res += '.'
                    flag1 = True
                    numerator = numerator * 10
                else:
                    #res += str(trade)
                    if '.' not in res:
                        res += '.'
                        flag1 = True
                        numerator = numerator * 10
                    else:
                        res += '0'
                        numerator_list.append(numerator)
                        numerator = numerator * 10 - trade * denominator
            else:
                res += str(trade)
                if '.' in res:
                    numerator_list.append(numerator)
                numerator = numerator - trade * denominator
                if flag1:
                    numerator = numerator * 10
            # 如果numerator在numerator_list中,则证明重复了
            if numerator in numerator_list:
                # 分两种情况,第一种是单位重复,第二种是多位重复
                # 单位重复
                if numerator == numerator_list[-1]:
                    res = res[:-1] + '(' + res[-1] + ')'
                    break
                # 多位重复
                else:
                    index = numerator_list.index(numerator) # 找到重复被除数的下标
                    point_index = res.index('.') # 找到小数点的位数
                    offset = 2 # 偏移量
                    if len(res[:point_index]) != 1:
                        offset = point_index + 1
                    res = res[: index+offset] + '(' + res[index+offset:] + ')'
                    break
            if numerator == 0:
                break
        if flag2:
            res = '-' + res
        return res


s = Solution()
print(s.fractionToDecimal(numerator = 420, denominator = 226))
        


# @lc code=end


以上是关于LeetCode第166题—分数到小数——Python实现的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode第166题—分数到小数——Python实现

leetcode-166. 分数到小数

LeetCode 405. 数字转换为十六进制数(补码的问题) / 166. 分数到小数(模拟长除法) / 482. 密钥格式化

LeetCode166 分数到小数

leetcode-166-分数到小数(用余数判断有没有出现小数的循环体)

LeetCode 166 分数到小数[字符串 哈希表] HERODING的LeetCode之路