Python面试宝典第35题:字符串相乘

35 篇文章 0 订阅 ¥19.90 ¥99.00

题目

        给定两个以字符串形式表示的非负整数num1和num2,返回num1和num2的乘积,它们的乘积也表示为字符串形式。

        注意:不能使用任何内置的BigInteger库或直接将输入转换为整数。

        备注:

        (1)1 <= num1.length, num2.length <= 200。

        (2)num1和num2只能由数字组成。

        (3)num1和num2都不包含任何前导零,除了数字0本身。

        示例 1:

输入: num1 = "2", num2 = "3"
输出: "6"

        示例 2:

输入: num1 = "123", num2 = "456"
输出: "56088"

手动实现乘法

        使用手动实现乘法来解决本题是一种直观且有效的方法,它模拟了我们在纸上进行大数乘法的方式。求解本题的主要步骤如下。

        1、初始化。创建一个结果数组result用于存储乘积的每一位。

        2、遍历乘法。从右到左遍历num1的每一位,对于num1的每一位,从右到左遍历num2的每一位。

        3、计算乘积。计算每一位的乘积,并加上进位。

        4、更新进位。更新进位,并将结果存入result数组。

        5、处理进位。遍历完成后,处理最后一次进位,并将result数组转换为字符串。

        根据上面的算法步骤,我们可以得出下面的示例代码。

def string_multiply_manually(num1, num2):
    result = [0] * (len(num1) + len(num2))

    # 遍历num1的每一位
    for i in range(len(num1) - 1, -1, -1):
        n1 = int(num1[i])
        # 遍历num2的每一位
        for j in range(len(num2) - 1, -1, -1):
            n2 = int(num2[j])
            # 计算乘积并加上进位
            product = n1 * n2 + result[i + j + 1]
            # 更新进位
            carry = product // 10
            result[i + j + 1] = product % 10
            # 更新当前位置的值
            result[i + j] += carry
    
    # 处理前导零
    i = 0
    while i < len(result) and result[i] == 0:
        i += 1
    
    # 转换成字符串
    return ''.join(map(str, result[i:]))

print(string_multiply_manually("2", "3"))
print(string_multiply_manually("123", "456"))

Karatsuba算法

        Karatsuba算法是由著名的俄罗斯数学家Karatsuba发明的,它以其在快速乘法算法领域的工作而闻名。Karatsuba算法利用了分治的思想,通过将大数分解为较小的部分来减少乘法的次数。其算法的主要特点如下:

        1、将两个大数分别拆分为高位和低位两个部分。

        2、利用公式 xy = (a * 10^n + b) * (c * 10^n + d) = ac * 10^(2n) + ((ad + bc) * 10^n) + bd 来计算乘法结果。其中a、b、c、d分别表示大数的高位和低位部分,n表示大数的位数一半的位置。

        3、通过递归地应用该算法,可以有效地减少所需的乘法次数。

        使用Karatsuba算法求解本题的主要步骤如下。

        1、基础情况。如果任意一个数字的长度小于等于1,则直接返回它们的乘积。

        2、分割数字。将两个数字分割成高位和低位,为后面的步骤做准备。

        3、递归计算。递归地计算高位乘积、低位乘积和交叉乘积。

        4、组合结果。利用上述结果,计算出最终的乘积。

        根据上面的算法步骤,我们可以得出下面的示例代码。

def string_multiply_by_karatsuba(num1, num2):
    def str_to_int(s):
        return int(s)
  
    def int_to_str(n):
        return str(n)
    
    # 基本情况
    if num1 == "0" or num2 == "0":
        return "0"
    if len(num1) < 10 or len(num2) < 10:
        return int_to_str(str_to_int(num1) * str_to_int(num2))
  
    # 分割数字
    n = max(len(num1), len(num2))
    half = n // 2
    high1 = num1[:half]
    low1 = num1[half:]
    high2 = num2[:half]
    low2 = num2[half:]
  
    # 递归计算
    z0 = string_multiply_by_karatsuba(low1, low2)
    z1 = string_multiply_by_karatsuba((str_to_int(low1) + str_to_int(high1)), 
                                      (str_to_int(low2) + str_to_int(high2)))
    z2 = string_multiply_by_karatsuba(high1, high2)

    # 计算最终结果
    result = int_to_str(str_to_int(z2) * (10 ** (2 * half)) + 
                        ((str_to_int(z1) - str_to_int(z2) - str_to_int(z0)) * 
                         (10 ** half)) + str_to_int(z0))
    return result

print(string_multiply_by_karatsuba("2", "3"))
print(string_multiply_by_karatsuba("123", "456"))

总结

        手动实现乘法时,对于两个长度为n的数字,需要遍历每一个数字位,因此时间复杂度为O(n^2)。空间复杂度为O(n),因为需要一个长度为2n的数组来保存乘积的结果。手动实现乘法的概念比较直观,容易理解和实现。但对于非常大的数字,时间复杂度较高,效率较低。

        Karatsuba算法通过递归地将大数分解为较小的部分来减少乘法次数,其时间复杂度大约为O(n^log2(3)) = O(n^1.585),这比传统的O(n^2)更高效。对于较大的数字,Karatsuba算法比传统的乘法更快。但其实现更为复杂,需要理解递归和分治的概念。

        实际上,快速傅立叶变换 (Fast Fourier Transform, 即FFT) 也可以用来高效地计算大数乘法。但其实现复杂性高,需要较强的数学背景支持,这里就不再赘述了。

💡 需要《Python面试宝典》完整源码的大佬们,可订阅专栏后,搜索微信公众号“希望睿智”私信获取。

  • 21
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

希望_睿智

您的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值