题解 | #大数乘法#

大数乘法

https://www.nowcoder.com/practice/c4c488d4d40d4c4e9824c3650f7d5571

Python3复现算法书上的分治法,两个相乘的数A,B可以分解为
(A1*10^(n/2)+A2)*(B1*10^(n/2)+B2)=10^n*A1*B1+10^(n/2)*(A1*B2+A2*B1)+A2*B2  ,(1)
其中A1*B2+A2*B1=(A1+A2)*(B1+B2)-A1*B1-A2*B2 ,     (2)
可以看到,(2)相比于(1)少做了一次乘法,因此时间复杂度可以减为O(N^1.59)左右
算法基本思想如下:

算法伪代码如下:(图中用的2进制,我用的十进制)

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param s string字符串 第一个整数
# @param t string字符串 第二个整数
# @return string字符串
#
class Solution:
    # 字符串乘法
    def solve(self, s: str, t: str) -> str:
        # write code here
        # 分治法
        num = max(len(s), len(t)) // 2
        # 递归出口
        if s == "" or t == "":
            return ""
        if num <= 2:
            return str(int(s) * int(t))

        # 将每个数字一分为2,(a*10^num+b)*(c*10^num+d)
        s_l, s_r = s[:-num], s[-num:]
        t_l, t_r = t[:-num], t[-num:]
        print(s_l, s_r)
        print(t_l, t_r)
        p1 = self.solve(s_l, t_l)  # a*c
        p2 = self.solve(s_r, t_r)  # b*d
        p3 = self.solve(self.str_add(s_l, s_r), self.str_add(t_l, t_r))  # (a+b)*(c+d)
        if p1 != "":
            res1 = self.add_zero(p1, num * 2)  # 10^n*(a*c)
        else:
            res1 = ""
        cun = self.str_sub(self.str_sub(p3, p1), p2)  # ((a+b)*(c+d)-a*c-b*d)
        res2 = self.add_zero(cun, num)  # 10^(n/2)*((a+b)*(c+d)-a*c-b*d)
        res = self.str_add(self.str_add(res1, res2), p2) # 10^n*(a*c)+10^(n/2)((a+b)*(c+d)-a*c-b*d)+b*d
        return res

    # 字符串加法
    def str_add(self, s: str, t: str) -> str:
        s = list(map(int, list(s)))  # 将s转化成数字数组
        s.reverse()  # 从低位开始计算
        t = list(map(int, list(t)))  # 将t转化为数字数组
        t.reverse()  # 从低位开始计算
        num = max(len(s), len(t)) + 1  # 最长串
        # 将两个串加0到等长
        for i in range(len(s) - 1, num):
            s.append(0)
        for i in range(len(t) - 1, num):
            t.append(0)
        carry = 0  # 进位
        res = [0] * num
        for i in range(num):
            cun = s[i] + t[i] + carry
            carry = (cun) // 10
            res[i] = str(cun % 10)
        # 去除多余的0
        while res[-1] == "0" and len(res) > 1:
            res.pop()
        res.reverse()
        return "".join(res)

    # 字符串减法
    def str_sub(self, s: str, t: str) -> str:
        # 大的减小的
        s = list(map(int, list(s)))  # 将s转化成数字数组
        s.reverse()  # 从低位开始计算
        t = list(map(int, list(t)))  # 将t转化为数字数组
        t.reverse()  # 从低位开始计算
        num = max(len(s), len(t)) + 1  # 最长串
        # 将两个串加0到等长
        for i in range(len(s) - 1, num):
            s.append(0)
        for i in range(len(t) - 1, num):
            t.append(0)
        carry = 0  # 借位
        res = [0] * num
        for i in range(num):
            cun = s[i] - t[i] - carry
            if cun < 0:
                # 不够借
                carry = 1
                cun += 10
            else:
                carry = 0
            res[i] = str(cun)
        # 去除多余的0
        while res[-1] == "0" and len(res) > 1:
            res.pop()
        res.reverse()
        return "".join(res)

    # 乘10的n次幂
    def add_zero(self, s: str, n) -> str:
        # 添加0,如s*10^n就是在s后面添加n个0
        s = list(s)
        res = "".join(s + ["0"] * n)
        return res

#分治进行递归#
全部评论

相关推荐

诨号无敌鸭:恭喜佬,但是有一个小问题:谁问你了?我的意思是,谁在意?我告诉你,根本没人问你,在我们之中0人问了你,我把所有问你的人都请来 party 了,到场人数是0个人,誰问你了?WHO ASKED?谁问汝矣?誰があなたに聞きましたか?누가 물어봤어?我爬上了珠穆朗玛峰也没找到谁问你了,我刚刚潜入了世界上最大的射电望远镜也没开到那个问你的人的盒,在找到谁问你之前我连癌症的解药都发明了出来,我开了最大距离渲染也没找到谁问你了我活在这个被辐射蹂躏了多年的破碎世界的坟墓里目睹全球核战争把人类文明毁灭也没见到谁问你了
点赞 评论 收藏
分享
ArisRobert:统一解释一下,第4点的意思是,公司按需通知员工,没被通知到的员工是没法去上班的,所以只要没被通知到,就自动离职。就是一种比较抽象的裁员。
点赞 评论 收藏
分享
1 2 评论
分享
牛客网
牛客企业服务