String算法提升_2/9:415. 字符串相加
题目描述
给定两个字符串形式的非负整数 num1
和num2
,计算它们的和并同样以字符串形式返回。
你不能使用任何內建的用于处理大整数的库(比如 BigInteger
), 也不能直接将输入的字符串转换为整数形式。
示例 1:
输入:num1 = "11", num2 = "123" 输出:"134"
示例 2:
输入:num1 = "456", num2 = "77" 输出:"533"
示例 3:
输入:num1 = "0", num2 = "0" 输出:"0"
提示:
1 <= num1.length, num2.length <= 104
num1
和num2
都只包含数字0-9
num1
和num2
都不包含任何前导零
要求完善函数
class Solution {
public:string addStrings(string num1, string num2) {}
};
原题地址:415. 字符串相加 - 力扣(LeetCode)
题目解析
算法原理:
1. 本题就是手工模拟加法运算。
2. 我们现有的材料就是俩字符串:既然要模拟加法——1)从个位开始,相加后处理进位,并得到本位结果 2)不断往前(意味着我们会使用一个循环)3) 那循环的条件呢?便是字符串遍历到越界,下标为-1时。
3. 每次将得到的本位结果都尾插在既定返回的字符串里,因为是将个位、十位、千位的结果尾插——所以最后需要逆置,便得到最终结果。
代码攥写
1.手工 “从个位开始算” → 代码 “双指针指向字符串末尾”
手工算的时候,我们会先找到两个数的个位(最右边的数字),比如 num1="456" 的个位是 6(最右边),num2="77" 的个位是 7(最右边)。
代码里用 双指针初始化 实现这个 “找个位” 的动作:
// p1指向num1的末尾(个位),p2指向num2的末尾(个位)
int p1 = num1.size() - 1, p2 = num2.size() - 1;
字符串的下标从 0 开始,size()-1 就是最末尾的下标,正好对应数字的 “个位”。
2. “相加 + 处理进位 + 得本位结果”
// 1. 取当前位数字(越界则补0,因为不能继续往下减了)
int val1 = (p1 >= 0 ? num1[p1--] - '0' : 0);
int val2 = (p2 >= 0 ? num2[p2--] - '0' : 0);// 2. “当前位相加+加进位”
int c = val1 + val2 + next;// 3. 更新进位,因为进位是下一次需要用的,所以next的定义在while循环外
next = c / 10;
int current_digit = current_sum % 10; // 本位结果(比如13%10=3,对应本位最终结果为3)// “把本位结果存入字符串”,需要 + '0'成为char类型
ret.push_back(current_digit + '0');
3. 循环条件——只要一个指针没越界(>=0),就继续循环
while (p1 >= 0 || p2 >= 0)
4.最后一个细节,当退出while后,意味着与num1或者num2对齐的数字位都已经得到最终结果了——但如果next还有一个进位呢?(比如:999 + 1)
所以还需要检查是否有遗漏的进位
if (next != 0)
{ret.push_back(next + '0');
}
5.还是前面那句话:每次将得到的本位结果都是尾插在既定返回的字符串里,因为是将个位、十位、千位的结果尾插——所以最后需要逆置,才能得到最终结果。
reverse(ret.begin(), ret.end());
完整参考代码
class Solution
{
public:string addStrings(string num1, string num2) {// 1. 初始化:结果字符串、双指针(指向末尾)、进位string ret;int next = 0;int p1 = num1.size()-1,p2 = num2.size()-1;// 2. 逐位计算:处理所有有效数字while(p1 >= 0 || p2 >= 0){// 取当前位数字(越界则取0)——记得能加的是数字,不是charint val1 = (p1 >= 0 ? num1[p1--]-'0' : 0);int val2 = (p2 >= 0 ? num2[p2--] - '0' : 0);// 计算当前位总和 与 更新下一轮的进位int c = val1 + val2 + next;next = c / 10;c = c%10;// 存储当前位结果,字符串尾插效率高ret.push_back(c+'0');}//3. 处理最后剩余的进位if(next) ret.push_back(next +'0');//4. 反转结果:低位在前 -> 高位在前(你就想:现在个位在最前面,调转一下才是真正结果)reverse(ret.begin(),ret.end());return ret;}
};