Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >LeetCode 43,一题学会高精度算法

LeetCode 43,一题学会高精度算法

作者头像
TechFlow-承志
发布于 2020-03-23 06:48:46
发布于 2020-03-23 06:48:46
1.2K00
代码可运行
举报
文章被收录于专栏:TechFlowTechFlow
运行总次数:0
代码可运行

今天和大家讨论的算法是高精度,对应的LeetCode是第43题。题面其实没什么好说的,以字符串的形式给定两个数字,要求返回这两个数字的乘积。之所以是以字符串的形式给数字是因为这个数字可能会非常大,题目当中给定的范围是110位的数字。对于Python来说这不是问题,但是对于C++和Java等语言来说这么大的数字是无法以int类型存储的,所以必须要使用字符串来接收。

如果你使用Python,你可以不用任何算法就AC这题,但是这没有任何意义。那么正确的方法应该怎么做呢?

高精度与打竖式

这就需要我们的高精度算法出场了,其实严格说起来高精度并不是一种算法,而是一种思想。这个思想非常朴素,我敢保证我们每一个人都学过。还记得小学的时候,我们计算多位数的乘法是怎么算的吗?大家应该都不陌生才对,就是打竖式,like this:

我们人类要打竖式是因为我们只能计算一位数以内的加减乘除,超过一位的人脑不能直接计算,我们就需要用纸笔记录下来进行计算。

纸笔计算的方法很简单,就是一位一位地计算,用每一位数字依次去计算乘法,最后再移位相加起来就得到结果了。

比如在上图的第一个例子当中,我们要计算15 * 16,我们先计算6 * 15的结果,再计算1 * 15,最后将两个结果错位相加,就得到了答案。我们要错位的原因也很简单,因为我们在计算15 * 1的时候,其实背后代表的是15 * 10。我们继续拆分问题,当我们计算6和15相乘的时候,又是怎么计算的呢?顺着这个思路,整个过程可以进一步被划分成先计算6和5相乘,再计算6和1相乘。

最后,我们把两个较大数字的相乘拆分成了在每一位上的数字相乘。到了这里,剩下的就简单了,也就是说我们可以把这两个很大的数字用两个数组来存储,数组当中的每一位存储数字上的一位。

比如我们要计算123 * 224, 我们的第一个数组是[1, 2, 3],我们的第二个数组是[2, 2, 4]。我们仿照乘法竖式中的方法计算这两个数组当中两两的乘积,并将它们拼装成答案。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
            1 2 3
   *  2 2 4
  ____________
      4 9 2
    2 4 6
  2 4 6
  ____________
  2 7 5 5 2

同样我们用数组来存储中间和最后的结果,最后的结果就是:[2, 7, 5, 5, 2]。由于题目需要我们要返回的是字符串,所以我们还需要将数组里的内容再拼接成字符串。

这种用数组来模拟数字进行加减乘除运算的方法就叫做高精度算法,相信大家也都看到了,严格说起来这并不是一个算法,而只是一种思想。今天的题目出的是乘法,我们利用同样的方法也可以计算加减和除法。其中加减法非常简单,而除法则要复杂得多,也是高精度当中最难实现的部分。这里我们不做过多的拓展,计算的方法同样是打竖式,感兴趣的同学可以自行实现。

进位和前导零

当我们理清楚了打竖式的方法之后,我们还要面临进位和前导零的问题。

进位应该很容易理解,我们需要在计算乘法的时候判断当前位置的元素是否大于等于10,如果超过10的话,我们则需要进行进位。我们只需要将它除以10,得到的结果就是我们需要进位的值。除此之外就是前导零的问题,我们都知道除了零以外的合法数字是不允许首位出现0的,但是由于我们计算的是乘法,所以当其中某一个数为0会得到整体的结果为0,但是表示在数组当中则是多个0.

举个简单的例子,比如123 * 0,最后得到的应该是0,但是由于我们用数组表示了乘法运算当中的每一位,并且还进行了加法计算,所以会导致出现000的结果。这种情况我们要做特殊的处理,不过这也不复杂。最后我们把上面所有的思路都整理一下,就可以得到结果了。

我们来看下代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution:
    
    def multiply(self, num1: str, num2: str) -> str:
        # 将字符串转化成数组
        # 翻转数组,因为我们用第0位表示个位
        arr1 = [ord(i) - ord('0') for i in num1][:: -1]
        arr2 = [ord(i) - ord('0') for i in num2][:: -1]
        
        # 创建结果数组,可以证明结果的长度最多是n + m
        n, m = len(arr1), len(arr2)
        ret = [0 for i in range(n + m + 1)]
        
        for i in range(n):
            for j in range(m):
                # 按位相乘,计算进位
                ret[i + j] += arr1[i] * arr2[j]
                if ret[i+j] >= 10:
                    ret[i+j+1] += ret[i+j] // 10
                    ret[i+j] %= 10
                    
        # 最后把数组再转化成字符串返回
        # 去除前导零
        result = ''.join(map(str, ret))[::-1].lstrip('0')
        return result if len(result) > 0 else '0'

今天的题只是Medium难度,并不算困难,会选这题的原因主要是为了高精度算法。高精度算法本身并不难,也并不常用即使是在算法比赛当中也不常见。但是它给了我们一个思路,当我们要计算的数值超过计算机目前承载能力的时候,我们还有什么方法?

当然这题我们也可以取巧,因为Python当中内置了大整数,当它检测到我们的计算结果超过范围的时候,会自动转化成大整数来进行计算。所以这题如果我们使用Python,可以只用几行代码搞定:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution:
    def multiply(self, num1: str, num2: str) -> str:
        num1 = int(num1)
        num2 = int(num2)
        return str(num1 * num2)
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-03-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Coder梁 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
48days强训——day6
示例1 输入: [9,3,7],[6,3] 返回值: {1,0,0,0} 说明: 如题面解释 示例2 输入: [0],[6,3] 返回值: {6,3} 备注: 1≤n,m≤1061≤n,m≤106 0≤ai,bi≤90≤ai​,bi​≤9
秋邱
2025/03/29
410
48days强训——day6
​LeetCode刷题实战43:字符串相乘
算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 !
程序员小猿
2021/01/20
4470
​LeetCode刷题实战43:字符串相乘
链表以及字符串数据求和及乘积问题
本篇文章分为三个部分也就是三道题来对一系列大数求和积问题做一下解答已经总结,这里正如题目所说的链表,字符串等,这些也不过是一个形式,其实可以归为一类,因此这里我们要知道真正的侧重点是在于如何去求和以及乘积? 这里也就是我们不能盲目的直接相加啊,相乘啊去求,因此可以把加以及乘的具体步骤模拟一下,最后得到最后答案,说白了也就是我们要一位一位来,而不是‘’一口气‘’!
羑悻的小杀马特.
2025/01/23
540
链表以及字符串数据求和及乘积问题
一天一大 lee(克隆图)难度:中等-Day20200813
给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。
前端小书童
2020/09/24
2970
一天一大 lee(克隆图)难度:中等-Day20200813
高精度算法解析与实现(c++)
在计算机科学中,高精度运算是指超出普通数据类型(如int或long long)所能表示的数值范围的计算。这些计算涉及到处理非常大的整数或浮点数,常见的应用场景包括大数加减乘除、密码学、科学计算等。在这篇博客中,我们将学习几种常见的高精度算法,并通过具体代码实现其功能,涵盖高精度加法、减法、乘法和除法。
平凡之路.
2025/02/22
2010
【C++】 —— 笔试刷题day_6
看题目我们可以发现,题目所给的数组范围特别大,所以,我们使用int、long long肯定是不行的;
星辰与你
2025/03/17
590
【C++】 —— 笔试刷题day_6
【Leetcode】string类刷题
接着,创建两个索引,begin和end,一个从前往后找,找到一个字母停止,另一个从后面找,找到字母停止,然后进行交换,保证begin<end,比较简单,代码如下:
用户11029103
2024/04/20
1070
【Leetcode】string类刷题
算法讲解之字符串
本文主要讲解算法中和字符串结合的题目,跟字符串结合的算法题种类丰富,主要是跟别的算法结合,下面介绍几道比较经典的题目~
用户11316056
2024/10/16
970
算法讲解之字符串
算法0基础之高精度加法模板+解题报告
文章目录 前言 高精度算法的实现 高精度加法 例题 前言 🤞秋名山码民的主页🤞 🎉欢迎关注🔎点赞👍收藏⭐️留言📝 🙏作者水平很有限,如果发现错误,一定要及时告知作者 高精度算法存在的意义: 在c++中变量的最大范围也不过是64位的大小,可是在实际的数据中难免出现超出范围的,从而由字符串(数组)引申出来了高精度的计算,用字符串来模拟每一位数字,用算术模拟计算高精度加法,高精度乘法 高精度算法的实现 高精度加法 for (int i = 0; i < maxlen; ++i) { av = (
秋名山码神
2022/12/13
3480
【蓝桥杯每日一题】3.16
刷题就像打游戏,蓝桥杯是终极大BOSS,每天的真题都是小怪——虽然爆率低,但装备(知识)掉不停!
f狐o狸x
2025/03/17
1051
【蓝桥杯每日一题】3.16
算法基础(二)| 高精度算法详解
适用于c++,java和python没有这个问题,因为java有大整数类,python自带,默认数是无限大。
timerring
2022/09/27
8480
算法基础(二)| 高精度算法详解
【C++经典例题】基于字符串实现大数相乘问题
在实际编程中,我们经常会遇到需要处理大整数的情况。由于编程语言中内置整数类型(如 int、long 等)有其表示范围的限制,当需要处理的整数超出这些范围时,就不能直接使用内置类型进行计算。
倔强的石头
2025/04/15
990
【C++经典例题】基于字符串实现大数相乘问题
运筹学与最优化理论基础——高精度加减乘除(C++实现)
在写单纯形算法时,发现了高精度分数存在bug与不足,所以必须对相关函数进行修改。主要有bug的函数是string DIVIDE_INT(string str1,string str2,int flag),之前是为了运算简单起见,对于特殊除数与被除数进行特定的判断来减小计算复杂度,但是发现存在逻辑bug,判断这些条件之后,未直接返回结果使得程序仍然会执行正常的除法操作,因此对这个bug进行修正。同时为了方便之后的单纯型算法的编写,在此又特意添加两个函数int Compare2Zero()和int Compare2Fraction(Fraction fraction),分别来比肩与0和分数fraction的大小。 在写两阶段单纯形算法时,发现了高精度分数中缺少相关取反和取倒数等接口导致代码出现大量重复代码。因此再次对高精度分数类进行修改。主要实现了分数取反和分数取倒数,并将整体代码进行了优化。由于两个函数过于简单,因此不对这两个函数进行讲解。
AI那点小事
2020/04/20
1.3K0
运筹学与最优化理论基础——高精度加减乘除(C++实现)
leetcode刷题(68)——43. 字符串相乘
给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。
老马的编程之旅
2022/06/22
3330
leetcode刷题(68)——43. 字符串相乘
高精度原理介绍及代码实现
高精度算法(High Accuracy Algorithm)的出现是为了处理超大数据的数学计算问题。在一般的科学计算中,我们可能会遇到需要计算小数点后几百位甚至更多的数字,或者处理几千亿、几百亿这样的大数字。这些数字超出了标准数据类型(如整型、实型)能够表示的范围,因此无法直接在计算机中正常存储和计算。
用户11039529
2024/05/24
1600
高精度原理介绍及代码实现
【C++】高精度算法讲解
高精度运算也称之为大数运算。即:在变量运算对象的数值范围为任何数据类型所无法容纳的情况下,采用整数数组存储(用字符串表示数字)。
Karos
2023/01/03
1.4K0
【C++】高精度算法讲解
【每日一题】43. Multiply Strings
Given two non-negative integers num1 and num2 represented as strings, return the product of num1 and num2, also represented as a string.
公众号-不为谁写的歌
2020/09/02
3530
【C++】string的9道OJ题
1. 这道题的难度算非常简单的了,我们可以定义两个变量来表示数组首尾位置的有效字符的下标,然后分别从前和从后向中间遍历,只要遇到字母就停下来,利用库函数swap进行交换。
举杯邀明月
2023/04/12
4300
【C++】string的9道OJ题
高精度算法和链表
计算机最初、也是最重要的应用就是数值运算。在编程进行数值运算时,有时会遇到运算的精度要求特别高,远远超过各种数据类型的精度范围;有时数据又特别大,远远超过各种数据类型的极限值。这种情况下,就需要进行“高精度运算”。
楚客追梦
2023/10/18
1990
【Day24】 LeetCode算法题 (注释详细+解题思路)[43. 字符串相乘 ] [1800. 最大升序子数组和]
解题思路: 我们需要获得两个字符串表示的正整数num1和num2的乘积,而且记过依旧以字符串形式输出。
.29.
2022/11/15
3400
【Day24】 LeetCode算法题 (注释详细+解题思路)[43. 字符串相乘 ] [1800. 最大升序子数组和]
相关推荐
48days强训——day6
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验