Leetcode-43.Multiply Strings

来源:互联网 发布:三毛的梦里花落知多少 编辑:程序博客网 时间:2024/05/27 02:32

本次做的是大数相乘的题目。


1. 题目

Given two non-negative integers num1 and num2 represented as strings, return the product of num1 and num2.

Note:

    1. The length of both num1 and num2 is < 110.
    2. Both num1 and num2 contains only digits 0-9.
    3. Both num1 and num2 does not contain any leading zero.
    4. You must not use any built-in BigInteger library or convert the inputs to integer directly.

给出两个非负的数字num1和num2,用字符串string来表示,返回num1和num2相乘的结果。
注意:
    1. num1和num2的长度小于110;
    2. num1和num2都是只包含0-9的数字;
    3. num1和num2度的高位不是0;
    4. 不能使用已有的BigInteger 库或者直接将输入转化为整数。
2.思路
题目很容易理解,就是字符串的相乘,最简单的思路,就是按照手算时的竖式乘法来计算:较长的数字num1在上,较短的数字 num2在下,举个例子。num1乘以num2的每一位,得到的结果存储起来,再进行相加。按照这种思路,存储结果可以用字符串也可以用数组。我是采用数组的形式。数组r初始化为"num2.length x(num1.length()+num2.length())"的大小,且全为0.因为num2的长度决定了num1要乘几次,如下面例子,num1要乘4次,得到四行结果。最后相加的时候,结果的位数最多是num1.length() + num2.length()这么长。因此,得到这个全0矩阵后,每一列相加,就相当于竖式的加法计算。
          1 2 3 4 5
x                 2 2 2 4
———————————— 
000049380000246900002469000024690000
————————————  
0 2 7 4 5 5 2 8 0
按照上面例子的算法,可以得到计算结果。在最高位时,判断如果是0,则舍弃该位,若是有进位,则需要保存。
注意的是,当num1或者num2其中一个是0时,不需要计算,直接返回字符串“0”;还有,num1始终是较长的字符串,num2是较短的字符串。
3.代码
string multiply(string num1, string num2) {     //如果两个字符串有一个为0,那么相乘结果直接为0      if (num1 == "0" || num2 == "0")      return "0";      //比较两个字符串的长度,长的作为num1      if (num1.length() < num2.length())      {     string s;     s = num1;     num1 = num2;     num2 = s;      }      int i,j;      int k=0;      int len = num1.length() + num2.length();      //定义一个初始化为全0的矩阵来存放num1乘以num2每一位的计算结果,矩阵行数是num2的长度,矩阵列数是num1长度+num2长度      int r[num2.length()][len];      for(i = 0; i < num2.length(); i ++)      for(j = 0; j < len; j ++)      r[i][j] = 0;      //c用于记录进位      int c = 0;      //num2的最后一位开始,num1也是从最后一位开始,依次按位相乘      for(i = num2.length()-1; i >= 0; i --){      for(j =  num1.length() - 1; j >=0 ; j --){      int temp = (num1[j]-'0') * (num2[i]-'0') + c;      c = temp / 10;      //num1乘以num2的第i位存放在第k行,k从0开始      r[k][i+j+1] = temp % 10;;      }      r[k][i+j+1] = c;      k ++;      c = 0;      }      //sum用于记录矩阵每一列数字加起来的结果,c记录进位      int sum = 0;      c = 0;      string res = "";      for(int col = len-1; col >= 0; col --){         for(int row = 0; row < num2.length(); row ++){      sum += r[row][col];      }         sum += c;      c= sum / 10;      //如果最高位这一列结果是0,则不需要加到res中      if((col == 0) && (sum == 0))     break;          res += (sum%10)+'0';      sum = 0;      }      //翻转字符串      reverse(res.begin(), res.end());      return res; }


4.优化的方法
字符串很长的时候,必然会有很多重复的数字,那么此时可以进行优化。定义一个int数组,记为h,大小为10,分别表示num2中数字0-9出现过没有,出现过,则将出现在第几位记录在数组h中。以上面例子来讲,当num1乘以num2中的4时,记录h[4]  = k, 表示在矩阵的第k行;当num1乘以num2中的第一个2时,记录h[2] ;那么当再次出num2中再出现2时,就可以直接从矩阵的r[h[2]]行取结果,放在当前行,并前移几个单位即可。
我认为这种做法在字符串长时会有一定的改进。代码添加修改部分如下:
     int h[10];      for(i = 0; i < 10; i ++)      h[i] = 0;      //c用于记录进位      int c = 0;      //num2的最后一位开始,num1也是从最后一位开始,依次按位相乘      for(i = num2.length()-1; i >= 0; i --){      if (h[(num2[i]-'0')] != 0)      {      int d = k - h[(num2[i]-'0')];      for(int l = len - 1; l >= d;l--)      r[k][l-d] = r[h[(num2[i]-'0')]][l];      }      else{      for(j =  num1.length() - 1; j >=0 ; j --){      int temp = (num1[j]-'0') * (num2[i]-'0') + c;      c = temp / 10;      //num1乘以num2的第i位存放在第k行,k从0开始      r[k][i+j+1] = temp % 10;;      }      h[(num2[i]-'0')] = k;      r[k][i+j+1] = c;      }      k ++;      c = 0;      }

 
0 0
原创粉丝点击