字符串相乘(43)

43. 字符串相乘 - 力扣(LeetCode)

解法 1:

class Solution {
public:
    string multiply(string num1, string num2) 
    {
        string res = "0";
        for (int i = 0; i < num2.size(); ++i) {
            string str = multiplyOneNum(num1, num2[num2.size() - 1 - i], i);
            res = add(res, str);
        }
        
        return res;
    }

private :
    string add(const string & num1, const string & num2)
    {
        string res;
        res.reserve(max(num1.size(), num2.size()) + 1);
    
        int idx1 = num1.size() - 1;
        int idx2 = num2.size() - 1;
        int carry = 0;
        while (idx1 >= 0 || idx2 >= 0 || carry > 0) {
            int num = 0;
            if (idx1 >= 0) {
                num += static_cast<int>(num1[idx1--] - '0');
            }
            if (idx2 >= 0) {
                num += static_cast<int>(num2[idx2--] - '0');
            }

            if (carry > 0) {
                num += carry;
            }

            carry = num / 10;
            num = num % 10;

            res.push_back(static_cast<char>(num + static_cast<int>('0')));
        }

        reverse(res.begin(), res.end());
        res.shrink_to_fit();
        return res;
    }

    string multiplyOneNum(const string & num1, const char & one_num , int times = 0)
    {
        if (one_num == '0' || num1 == "0") {
            return "0";
        }

        string res;

        res.reserve(num1.size() + 1 + times);
        int carry = 0;
        for (int i = num1.size() - 1; i >= 0; --i) {
            int num = static_cast<int>(num1[i] - '0') * static_cast<int>(one_num - '0');
            if (carry > 0) {
                num += carry;
            }
            carry = num / 10;
            num = num % 10;
            res.push_back(static_cast<char>(num + static_cast<int>('0')));
        }
        if (carry) {
            res.push_back(static_cast<char>(carry + static_cast<int>('0')));
        }

        reverse(res.begin(), res.end());
        if (times > 0) {
            res.append(times, '0');
        }

        res.shrink_to_fit();
        return res;
    }
};

总结:

设num1的长度是m,num2的长度是n,multiplyOneNum函数的时间复杂度是O(m), 由于result的长度是m + n,所以add函数的时间复杂度是O(m+n),外面又一层循环n,所以时间的计算复杂度是O(mn) + O(mn + n2),即O(mn + n2)。无论是 multiplyOneNum函数还是add函数最长使用的字符串长度是m+n,所以空间复杂度是O(m+n)。

解法 2:

class Solution {
public:
    string multiply(string num1, string num2) 
    {
        if (num1 == "0" || num2 == "0") {
            return "0";
        }
        vector<int> num_restore(num1.size() + num2.size(), 0);
        for (int i = num1.size() - 1; i >= 0; --i) {
            for (int j = num2.size() - 1; j >= 0; --j) {
                num_restore[(num1.size() - 1 - i) + (num2.size() - 1 - j)] += static_cast<int>((num1[i] - '0')) * static_cast<int>((num2[j] - '0'));
            }
        }

        int add = 0;
        for (int i = 0; i < num_restore.size(); ++i) {
            num_restore[i] = num_restore[i] + add;
            add = num_restore[i] / 10;
            num_restore[i] =  num_restore[i] % 10;
        }

        string res;

        if (num_restore.back() > 0) {
            res.reserve(num1.size() + num2.size());
            res.push_back(static_cast<char>(static_cast<int>('0') + num_restore.back()));
        }else {
            res.reserve(num1.size() + num2.size() - 1);
        }

        for (int i = num_restore.size() - 2; i >= 0; --i) {
            res.push_back(static_cast<char>(static_cast<int>('0') + num_restore[i]));
        }

        return res;
    }
};

总结:

如果num1的长度为m,num2的长度为n,则num1和num2乘积的长度为m+n或者m+n-1,证明如下:

如代码所示,时间计算复杂度是O(mn),空间上需要一个数组num_restore,其长度为O(m+n),和解法1相比,因为计算量更少(计算量上2mn + n2 VS mn),且省去了字符串来回转换的计算,在运算效率上,解法2比解法1要快至少5倍以上(leetcode上的运行结果来看),不得不说这就是算法的厉害!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值