博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
leetcode:Multiply Strings
阅读量:5998 次
发布时间:2019-06-20

本文共 4702 字,大约阅读时间需要 15 分钟。

Given two numbers represented as strings, return multiplication of the numbers as a string.

Note: The numbers can be arbitrarily large and are non-negative.

第一眼看到这个题目,潜意识里觉得直接将字符串转换为数字相乘,然后将结果再转换为字符串,难道这题考的是字符串与数值之间的转换?

细看,发现数字可能非常大,那么问题来了:这个数据类型怎么定义呢?显然这种思路完全是错的了。

那么怎么解决这个问题呢?仔细一想问题可能在于如何理解这个乘法过程(题目中multiply可是关键字)了。由于经验尚浅,花了一些时间去琢磨,最后参照一些资料做出了如下分析:(算法题还是有很多值得用心思考的地方的,要学会抓住解决问题的痛点,和把握细节)

1、要模拟竖式乘法的计算过程(透过问题看本质)

2、这个过程有乘法思维,还有加法思维在里面(因为涉及到进位)

3、要把乘法和加法操作过程分清楚,每次一个新位与被乘数相乘之前,都要加上进位再处理。(注意细节)

4、为了顺应习惯,把两个数字reverse过来再操作,最后还原顺序。

代码如下:

class Solution {public:string multiply(string num1, string num2) {    int m = num1.size(), n = num2.size();//字符串元素个数    if (num1 == "0" || num2 == "0") return "0";    vector
res(m+n, 0); reverse(begin(num1),end(num1));//字符串反转 reverse(begin(num2),end(num2)); for (int i = 0; i < n; ++i) for (int idx = i, j = 0; j < m; ++j) res[idx++] += (num2[i]-'0')*(num1[j]-'0');// 字符转化为数字然后相乘(ascll码) int carry = 0; for (int i = 0; i < m+n; ++i) { int tmp = res[i]; res[i] = (tmp+carry)%10; carry = (tmp+carry)/10;//进位 } string str(m+n,'0'); for (int k = 0, i = res.size()-1; i >= 0; --i) str[k++] = res[i]+'0';//还原顺序 auto idx = str.find_first_not_of('0');//将str字符串中第一个不匹配字符‘0’的索引值赋给idx return str.substr(idx);//从起始字符序号idx开始取得str中的子字符串(消除了前面的0)}};

 其他解法:

1、 class Solution {public:string multiply(string num1, string num2) {    string sum(num1.size() + num2.size(), '0');    for (int i = num1.size() - 1; 0 <= i; --i) {        int carry = 0;        for (int j = num2.size() - 1; 0 <= j; --j) {            int tmp = (sum[i + j + 1] - '0') + (num1[i] - '0') * (num2[j] - '0') + carry;            sum[i + j + 1] = tmp % 10 + '0';            carry = tmp / 10;        }        sum[i] += carry;    }    size_t startpos = sum.find_first_not_of("0");    if (string::npos != startpos) {        return sum.substr(startpos);    }    return "0";}};

 

This is an example of the pretty straightforward but very efficient C++ solution with 8ms runtime on OJ. It seems most of people here implemented solutions with base10 arithmetic, however that is suboptimal. We should use a different base.

This was a hint. Now stop, think, and consider coding your own solution before reading the spoiler below.

The idea used in the algorithm below is to interpret number as number written in base 1 000 000 000 as we decode it from string. Why 10^9? It is max 10^n number which fits into 32-bit integer. Then we apply the same logic as we used to hate in school math classes, but on digits which range from 0 to 10^9-1.

You can compare the multiplication logic in other posted base10 and this base1e9 solutions and you'll see that they follow exactly same pattern.

Note, that we have to use 64-bit multiplication here and the carry has to be a 32-bit value as well

class Solution {public:    void toBase1e9(const string& str, vector
& out) { int i = str.size() - 1; uint32_t v = 0; uint32_t f = 1; do { int n = str[i] - '0'; v = v + n * f; if (f == 100000000) { out.push_back(v); v = 0; f = 1; } else { f *= 10; } i--; } while (i >= 0); if (f != 1) { out.push_back(v); } } string fromBase1e9(const vector
& num) { stringstream s; for (int i = num.size() - 1; i >= 0; i--) { s << num[i]; s << setw(9) << setfill('0'); } return s.str(); } string multiply(string num1, string num2) { if (num1.size() == 0 || num2.size() == 0) return "0"; vector
d1; toBase1e9(num1, d1); vector
d2; toBase1e9(num2, d2); vector
result; for (int j = 0; j < d2.size(); j++) { uint32_t n2 = d2[j]; int p = j; uint32_t c = 0; for (int i = 0; i < d1.size(); i++) { if (result.size() <= p) result.push_back(0); uint32_t n1 = d1[i]; uint64_t r = n2; r *= n1; r += result[p]; r += c; result[p] = r % 1000000000; c = r / 1000000000; p++; } if (c) { if (result.size() <= p) result.push_back(0); result[p] = c; } } return fromBase1e9(result); }};

  

 

 

转载于:https://www.cnblogs.com/carsonzhu/p/4563268.html

你可能感兴趣的文章
如何实现python的mysql连接池并加入缓存过期
查看>>
every derived table must have its own alias
查看>>
园区网NAT+OSPF实现【神州数码设备】
查看>>
在koa2中使用handlebars.js的layout的用法
查看>>
javaWeb的艰辛之路
查看>>
在windows命令行中查询MySQL乱码
查看>>
nmap代码总结
查看>>
Elasticsearch安装配置
查看>>
决心书
查看>>
IntelliJ Idea 常用快捷键列表
查看>>
linux crontab 目录
查看>>
spring boot h2内存数据库以及mysql配置
查看>>
IT行业为什么需要更多的女性?
查看>>
关于智能合约的真相
查看>>
2015年9月25日
查看>>
给孩子失败的机会
查看>>
[二叉树专题]求二叉树的前中后遍历(递归,迭代)
查看>>
RabbitMQ概念简介
查看>>
Linux学习之旅 - 第一天
查看>>
js常用正则
查看>>