• 【43. 字符串相乘】


    字符串相加

    题目来源

    力扣(LeetCode): 字符串相乘

    题目描述

    给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。

    注意:不能使用任何内置的 BigInteger 库或直接将输入转换为整数。

    示例1

    输入

    num1 = “2”, num2 = “3”

    输出

    “6”

    示例2

    输入

    num1 = “123”, num2 = “456”

    输出

    “56088”

    提示

    • 1 <= num1.length, num2.length <= 200
    • num1 和 num2 只能由数字组成。
    • num1 和 num2 都不包含任何前导零,除了数字0本身。

    思路分析

    • 排除有’0’的情况
    • 定义一个字符串保存乘积结果,这个串的长度是两个乘数长度之和
    • 两层循环,从低位到高位开始相乘,这里必须将两个数全部转换为int类型相乘,定义临时变量保存乘积
    • ▲用k表示当前乘积要保存在的位置,如果有进位则将进位结果保存在k-1的位置,由于char类型范围较小,所以乘积不能直接与ret当前位置的值相加,否则有可能超出char类型取值范围,如:得到乘积81若与’0’相加超出char类型范围。正确的处理方式:先将乘积结果进位保留个位与ret当前位相加,并再次处理加和的进位
    • 结果放入字符串中时要转换成char类型,因为字符串每个位置都被初始化为了’0’,所以只需要将乘积加到对应位置即可
    • 得到结果后,去除最高位的’0’

    代码展示

    class Solution {
    public:
        string multiply(string num1, string num2) {
            //有一个乘数为0则积为0
            if (num1 == "0" || num2 == "0")
            {
                return "0";
            }
    
            //找较长的串作左操作数(个人习惯,这步可以省略)
            if (num1.size() < num2.size())
            {
                num1.swap(num2);
            }
            int LeftSize = num1.size();
            int RightSize = num2.size();
            //保存乘积的字符串,两个数乘积最大位数为两个数位数之和
            int RetSize = LeftSize + RightSize;
            string ret(RetSize, '0');
             
            int m = 1;//m标记保存结果数据的起始位
            for (int i = RightSize - 1; i >= 0; i--)
            {
                int k = RetSize - m;
                for (int j = LeftSize - 1; j >= 0; j--)
                {
                    //定义临时变量保存乘积,int类型
                    int temp = (num2[i] - '0') * (num1[j] - '0');
                    //进位,因为乘积最大位81,加上'0'会超出char类型范围,所以要分两次处理进位
                    ret[k - 1] += temp / 10;
                    temp %= 10;
                    ret[k] += temp;
                    //临时变量temp加到ret字符串中后还要再次处理进位
                    while (ret[k] > '9')
                    {
                        ret[k] -= 10;
                        ret[k - 1] += 1;
                    }
                    k--;//ret中保存结果的位置左移
                }
                m++;//ret中保存结果的起始位置左移一位
            }
            //去除最高位的'0'
            int count = 0;
            for (auto ch : ret)
            {
                if (ch != '0')
                {
                    break;
                }
                count++;
            }
            ret.erase(0, count);
            return ret;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    总结

    难点及易错点:

    • 忽略有’0’的情况
    • 两次处理进位结果
    • 对于int类型,可以用“除10”和“模10”处理进位
    • 保存结果的字符串位置的偏移,内层循环每次结束左移一位,外层循环每轮结束将起始位置左移一位
    • 去除结果最高位的’0’
  • 相关阅读:
    TaskDispatcher源码解析
    基于开源模型搭建实时人脸识别系统(五):人脸跟踪
    php包管理器composer浅析,thinkphp框架原理浅析
    西部是真的地广人稀啊,常用地市东西分布差异明显
    SCI一区 | Matlab实现POA-TCN-BiGRU-Attention鹈鹕算法优化时间卷积双向门控循环单元注意力机制多变量时间序列预测
    LeetCode 513找树左下角的值 112路径总和113路径总和ii 106从中序与后序遍历序列构造二叉树
    基于JavaWeb+SSM+微信小程序基金优选系统的设计和实现
    软件基础的理论
    高项 沟通管理论文
    MySQL的复合查询
  • 原文地址:https://blog.csdn.net/qq_44631587/article/details/126234399