【数据结构与算法】之深入解析“字符串相加”的求解思路与算法示例

举报
Serendipity·y 发表于 2022/02/17 00:42:52 2022/02/17
【摘要】 一、题目要求 给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和并同样以字符串形式返回。不能使用任何內建的用于处理大整数的库(比如 BigInteger), 也不能直接将输入的字符串转换...

一、题目要求

  • 给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和并同样以字符串形式返回。
  • 不能使用任何內建的用于处理大整数的库(比如 BigInteger), 也不能直接将输入的字符串转换为整数形式。
  • 示例 1:
输入:num1 = "11", num2 = "123"
输出:"134"

  
 
  • 1
  • 2
  • 示例 2:
输入:num1 = "456", num2 = "77"
输出:"533"

  
 
  • 1
  • 2
  • 示例 3:
输入:num1 = "0", num2 = "0"
输出:"0"

  
 
  • 1
  • 2
  • 提示:
    • 1 <= num1.length, num2.length <= 104;
    • num1 和num2 都只包含数字 0-9;
    • num1 和num2 都不包含任何前导零。

二、求解算法

① 模拟

  • 本题只需要对两个大整数模拟「竖式加法」的过程,竖式加法就是平常学习生活中常用的对两个整数相加的方法,回想一下在纸上对两个整数相加的操作,是不是如下图将相同数位对齐,从低到高逐位相加,如果当前位和超过 10,则向高位进一位?因此只要将这个过程用代码写出来即可。

在这里插入图片描述

  • 具体实现也不复杂,定义两个指针 i 和 j 分别指向 num1 和 num2 的末尾,即最低位,同时定义一个变量 add 维护当前是否有进位,然后从末尾到开头逐位相加即可。你可能会想两个数字位数不同怎么处理,这里我们统一在指针当前下标处于负数的时候返回 0,等价于对位数较短的数字进行了补零操作,这样就可以除去两个数字位数不同情况的处理。
  • C++ 示例:
class Solution {
public:
    string addStrings(string num1, string num2) {
        int i = num1.length() - 1, j = num2.length() - 1, add = 0;
        string ans = "";
        while (i >= 0 || j >= 0 || add != 0) {
            int x = i >= 0 ? num1[i] - '0' : 0;
            int y = j >= 0 ? num2[j] - '0' : 0;
            int result = x + y + add;
            ans.push_back('0' + result % 10);
            add = result / 10;
            i -= 1;
            j -= 1;
        }
        // 计算完以后的答案需要翻转过来
        reverse(ans.begin(), ans.end());
        return ans;
    }
};

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • Java 示例:
class Solution {
    public String addStrings(String num1, String num2) {
        int i = num1.length() - 1, j = num2.length() - 1, add = 0;
        StringBuffer ans = new StringBuffer();
        while (i >= 0 || j >= 0 || add != 0) {
            int x = i >= 0 ? num1.charAt(i) - '0' : 0;
            int y = j >= 0 ? num2.charAt(j) - '0' : 0;
            int result = x + y + add;
            ans.append(result % 10);
            add = result / 10;
            i--;
            j--;
        }
        // 计算完以后的答案需要翻转过来
        ans.reverse();
        return ans.toString();
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

② 双指针

  • 设定 n1,n2 两指针分别指向 num1,num2 尾部,模拟人工加法;
    • 计算进位: 计算 carry = tmp // 10,代表当前位相加是否产生进位;
    • 添加当前位: 计算 tmp = n1 + n2 + carry,并将当前位 tmp % 10 添加至 res 头部;
    • 索引溢出处理: 当指针 n1 或 n2 走过数字首部后,给 n1,n2 赋值为 0,相当于给 num1,num2 中长度较短的数字前面填 0,以便后续计算。
    • 当遍历完 num1,num2 后跳出循环,并根据 carry 值决定是否在头部添加进位 1,最终返回 res 即可。
  • 初始状态:

在这里插入图片描述

  • n1,n2 两指针分别指向 num1,num2 尾部:

在这里插入图片描述

  • n1,n2 两指针继续分别指向 num1,num2 的十位:

在这里插入图片描述

  • 以此类推,直到最高位:

在这里插入图片描述

  • 最后得出结果:

在这里插入图片描述

  • Java 示例:
class Solution {
    public String addStrings(String num1, String num2) {
        StringBuilder res = new StringBuilder("");
        int i = num1.length() - 1, j = num2.length() - 1, carry = 0;
        while(i >= 0 || j >= 0){
            int n1 = i >= 0 ? num1.charAt(i) - '0' : 0;
            int n2 = j >= 0 ? num2.charAt(j) - '0' : 0;
            int tmp = n1 + n2 + carry;
            carry = tmp / 10;
            res.append(tmp % 10);
            i--; j--;
        }
        if(carry == 1) res.append(1);
        return res.reverse().toString();
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • Python 示例:
class Solution:
    def addStrings(self, num1: str, num2: str) -> str:
        res = ""
        i, j, carry = len(num1) - 1, len(num2) - 1, 0
        while i >= 0 or j >= 0:
            n1 = int(num1[i]) if i >= 0 else 0
            n2 = int(num2[j]) if j >= 0 else 0
            tmp = n1 + n2 + carry
            carry = tmp // 10
            res = str(tmp % 10) + res
            i, j = i - 1, j - 1
        return "1" + res if carry else res

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

文章来源: blog.csdn.net,作者:Serendipity·y,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/Forever_wj/article/details/122782907

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。