这个题是个大数乘法运算的题,两个乘数以string的形式给出,求他们相乘的结果,题目给的限制条件是:
1.所给的数字可以任意的大,但是不为负数
2.不能将题目所给的string转化为整数
3.不能引入大数运算相关的库
从题目的描述中我知道了这个题让我们自己去实现大数运算的乘法,就是这么个意思,那么我们开始吧:在纸上算的时候我们都会,可是用程序去做的时候就比较难了吧,而且乘法运算从右往左运算的,我们怎么往string的头部插入一个字符串呢?不用担心,我们请看下图:
既然从右往左运算的时候字符串不好操作,那么我们就将从右往左运算的结果从左往右存储,最后再反转字符串就可以解决了,这样的做法还有一些其他问题需要注意,比如 0 的处理,什么地方得添加 0 ,什么位置不用添加 0;还有就是进位的处理,写了两个函数一个用来计算乘法一个用来处理进位问题,因为我发现这两个功能不能复用,那么请看我的代码吧,其中有很多细节的地方需要注意,这道题考的就是细心的程度!
class Solution { public: string multiply(string num1, string num2) { /* 这个题的意思是返回两个大数相乘的结果 两个乘数可以很大且非负 不能将字符串转化为int 不能使用大数相关的库 */ string ret = ""; int sz1 = num1.size(); int sz2 = num2.size(); if (sz1 == 1 && num1[0] == '0' || sz2 == 1 && num2[0] == '0') { ret.push_back('0'); return ret; } //先往右进位,最后将结果逆置一下 for (int i = sz1-1; i >=0; --i) { int begin = sz1 - i - 1; for (int j = sz2-1; j >= 0; --j) { int tmp = (num1[i] - '0') * (num2[j] - '0'); carrybit(ret, begin, tmp); ++begin; } } //逆序 reverse(ret); return ret; } void carrybit(string& str, int begin, int num) { const int first = begin; if (num == 0) { if (begin >= str.size()) { // 相乘的结果为 0 且出现在最后面的位置,这个时候得补上0,否则缺位 str.push_back('0'); } } while (num) { int cur = num % 10; if (begin >= str.size()) {//在最后面的位置上添加的时候得添加‘字符’ str.push_back(cur + '0'); ++begin; } else {//在中间的位置上只需要加‘整数’ str[begin++] += cur; } num /= 10; } //判断当前位是否产生进位 int bigger = str[first] - '0'; if (bigger >= 10) {//判断当前位是否产生了进位,若进位则处理进位 curcarrybit(str, first, bigger); } } //进位处理函数 void curcarrybit(string &str, int begin, int num) { int first = begin; while (num) { int cur = num % 10; if (begin >= str.size()) { str.push_back(cur + '0'); ++begin; } else { if (first == begin) {//当前位产生进位,留下余下的,所以用赋值语句 str[begin++] = (cur + '0'); } else {//进位的数目补到后面的位置上 str[begin++] += cur; } } num /= 10; } } //翻转字符串 void reverse(string & s) { int right = s.size() - 1; int left = 0; while (left < right) { swap(s[left], s[right]); ++left; --right; } } };
最终结果如下:
我觉得这个题我是按照乘法原则一步一步去实现的,这种的做法好像不是最优的,但是我没有想出更优的方法来,不知道看到我的文章的人有没有更优的方法,如果有的话希望画上你几秒钟的时间指点指点。
时间: 2024-11-04 00:15:01