题目描述:
给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和。 注意:
- num1 和num2 的长度都小于 5100.
- num1 和num2 都只包含数字 0-9.
- num1 和num2 都不包含任何前导零。
- 你不能使用任何內建 BigInteger 库, 也不能直接将输入的字符串 转换为整数形式。
例:
输入 :"37459670" "4567087"
输出 : "42026757"
解题思路
题目意思就是说拿两个数字字符串,计算他们转为为数字相加的和,最后的结果也要是个字符串,但是不允许你直接把这两个数字字符串转化为数字直接相关,如果那么简单就完事了就莫得意思了啊。
我的想法是低位开始相加,从 num1 ,num2 的尾部开始计算,模拟人工加法。利用把两个字符串分割,用两个栈ar_num1,ar_num2分别存起来,栈顶为最低位元素,用一个变量result来存储最终返回的结果,这是个字符串,一开始为空串,用每次计算都取栈顶元素相加,用tmp保存单次相加的结果,两栈顶元素加完后,再加上进位数add(为0或者1),除10后取得得余数便是本次相加得结果,与上一轮的result拼起来便得到当前最新结果。之后便根据是否有进位设置add为0或者1,把单次结算结果tmp置为0,然后继续执行循环
最后栈都为空,但有可能上一轮的相加结果会产生进位,所有再得判断一下是否有进位,有则result前面再添1
下面是详细版的代码,注意,这是方便理解的代码,不太简洁,下面有简洁点的
方便理解版代码
/**
* @param {string} num1
* @param {string} num2
* @return {string}
*/
var addStrings = function(num1, num2) {
const ar_num1 = num1.split('') //分割数字字符串num1,存于栈ar_num1
const ar_num_2 = num2.split('') //分割数字字符串num2,存于栈ar_num2
let tmp = 0; //保存单次栈顶相加结果
let add = 0; //保存进位
let resut = ''; //保存最终结果,注意一开始为空字符串
while(ar_num1.length || ar_num_2.length) { //当任一栈不为空,代表还没结束
if(ar_num1.length) { //若ar_num1不为空,tmp
tmp += (+ar_num1.pop())
}
if(ar_num_2.length) { //若ar_num2不为空,则取栈顶元素转为数字加到tmp
tmp += (+ar_num_2.pop())
}
resut = (tmp+add) % 10 + resut // 单次结果加上进位后,取余数 与result相加(字符串相拼)
add = (tmp + add) > 9 ? 1 : 0 // 取进位
tmp = 0 //重置单次相加结果
}
if(add !== 0) { //若最后有进位,再在最终结果前添1
resut = 1 + resut
}
return resut
};
简洁版代码
从 num1 ,num2 的尾部开始计算,模拟人工加法,保存到 tmp 中;
计算 tmp 的个位数,并添加到 result 的头部,这里的 result 是 string 类型,不是 number 类型;
计算进位,改成 tmp,进行下次循环
索引溢出处理:循环结束,根据 tmp 判断是否有进位,并在 result 头部添加进位 1
返回 result
var addStrings = function(num1, num2) { let a = num1.length, b = num2.length, result = '', tmp = 0 while(a || b) { a ? tmp += +num1[--a] : '' b ? tmp += +num2[--b] : ''result = tmp % 10 + result if(tmp > 9) tmp = 1 else tmp = 0 } if (tmp) result = 1 + result return result
};
复杂度分析:
- 时间复杂度 O(max(M,N)) (M N分别为两字符串的长度)
- 空间复杂度 O(1)
本文使用 mdnice 排版