大数相加 | 刷题打卡

233 阅读3分钟

本文正在参与掘金团队号上线活动,点击 查看大厂春招职位

一、题目描述

给出两个很大的整数,求出两个整数之和。

示例:

输入:['813257907624', '92135218459']
输出:'905393126083'

二、思路分析

首先我们来回想一下列竖式(也就是加、减、乘、除的计算过程):

  813257907624
+  92135218459
----------------
  905393126083

那么,我们为什么要使用列竖式来进行运算呢?
因为对于这么大的整数进行相加,是无法直接计算出结果的,所以需要把计算的过程拆解为一个又一个的子过程。

打个比方 624 + 459 是不是相对来说计算起来比较麻烦,那么 4 + 92 + 5 + 16 + 4 计算起来是不是就没有那么麻烦了?

实际上使用程序来计算也是一样的。

我们只需要把一个大运算,拆解成若干个小运算,就像列竖式一样的进行按位计算,即可。

注: 需要注意的是,因为整数非常的大,超过了 Number 类型的长度,所以一般是使用字符串或者数组进行表示的,那么展示的时候一般是以字符串的形式,计算的时候一般是以数组的形式。

三、AC 代码

/**
 * 合并剩余不用进行计算的数值
 * @param { String[] } arr 剩余数值的数组
 * @param { Number } rec 进位
 * @param { Number[] } res 计算后的数组
*/
function mergeSurplusString(arr, rec, res) {
    if(arr.length && rec) {
        arr[arr.length - 1] = Number(arr[arr.length - 1]) + rec
        res.unshift(...arr)
    }
}

/**
 * 合并剩余不用进行计算的数值
 * @param { String } s1 整数 1
 * @param { String } s2 整数 2
 * @returns { String } 计算后的数值
*/
function sum (s1, s2) {
    // 传参类型判断
    if( typeof s1 !== 'string' ||  typeof s2 !== 'string' ) {
        throw new TypeError('参数不是字符串')
    }
    
    // 分割字符串为数组
    const _s1 = s1.split('')
    const _s2 = s2.split('')
    
    // 进位
    let rec = 0
    
    // 计算结果
    const res = []
    
    // 当 s1 和 s2 都有数值的情况,需要进行按位运算
    while(_s1.length && _s2.length) {
        // 获取 末尾 的数值 (因为计算是从个位开始算的,当然也可以反转数组后从数组头部开始计算)
        const p1 = _s1.pop()
        const p2 = _s2.pop()
        
        // 计算和
        const sum = Number(p1) + Number(p2) + rec
        
        // 获取进位
        rec = Math.floor(sum / 10)
        
        // 获取个位
        res.unshift(sum % 10)
    }
    
    // 合并剩余的数值
    mergeSurplusString(_s1, rec, res)
    mergeSurplusString(_s2, rec, res)
    
    // 返回计算后的字符串
    return res.join('')
}

console.log('sum:', sum('813257907624', '92135218459')) // sum: 905393126083

四、总结

大数相加是一道非常经典的题目哈,面试中出现的概率相当之大,而且是一道在业务场景中用的到的算法,所以还是很重要的。

其实关键点就是 列竖式 ,然后按位去逐个的进行运算。

本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情