zoukankan      html  css  js  c++  java
  • 算法:大整数相乘问题

      给定两个数字作为字符串。这些数字可能非常大(可能不适合int long int int),或许相乘在计算机可能溢出了,所以任务是找到这两个数字的乘积。

    1 Input : num1 = 4154  
    2         num2 = 51454
    3 Output : 213739916 
    4 
    5 Input :  num1 = 654154154151454545415415454  
    6          num2 = 63516561563156316545145146514654 
    7 Output : 41549622603955309777243716069997997007620439937711509062916

      我们可以基于数学思想来分解两个大整数的相乘问题

      从输入的第二个数字最后一位开始乘以输入的第一个数字然后,我们将第二个数字的倒数第二位数字与第一个数字相乘,依此类推。将所有这些乘法相加在相加时,将第 i个乘法移位了。

      以下解决方案中使用的方法是仅保留一个数组以获取结果。循环遍历所有数字的第一个和第二个数字,并将结果添加到适当的位置。其时间复杂度为 O(m * n),空间复杂度为 O(m+n),m 和 n 分别为两个大整数字符串的长度。

      1 package algorithm;
      2 
      3 /**
      4  * 大整数相乘问题
      5  */
      6 public class BIgIntMultiply {
      7     /**
      8      * 以字符串的形式输入两个大整数做乘法
      9      *
     10      * @param num1 整数1
     11      * @param num2 整数2
     12      * @return
     13      */
     14     private static String multiply(String num1, String num2) {
     15         int len1 = num1.length();
     16         int len2 = num2.length();
     17         if (len1 == 0 || len2 == 0)
     18             return "0";
     19 
     20         /* 将结果数以相反的顺序保存在数组中 */
     21         int[] result = new int[len1 + len2];
     22 
     23         /* 以下两个索引用于查找结果中的位置(移位) */
     24         int i_n1 = 0;
     25         int i_n2 = 0;
     26 
     27         /* 在num1中从右到左 */
     28         for (int i = len1 - 1; i >= 0; i--) {
     29             /* 临时保存需要进位的数 */
     30             int carry = 0;
     31             int n1 = num1.charAt(i) - '0';
     32 
     33             /* 在num2中每个数字的乘法运算后向左移动位置 */
     34             i_n2 = 0;
     35 
     36             /* 在num2中从右向左移动 */
     37             for (int j = len2 - 1; j >= 0; j--) {
     38                 /* 取第二个数字的当前数字 */
     39                 int n2 = num2.charAt(j) - '0';
     40 
     41                 /* 将当前数字与第一个数字相乘,然后将结果添加到先前存储的结果charAt当前位置 */
     42                 int sum = n1 * n2 + result[i_n1 + i_n2] + carry;
     43 
     44                 /* 用于下一个迭代相加 */
     45                 carry = sum / 10;
     46 
     47                 /* 存储结果 */
     48                 result[i_n1 + i_n2] = sum % 10;
     49 
     50                 i_n2++;
     51             }
     52 
     53             /* 到最后还有进位值则移位放上去 */
     54             if (carry > 0)
     55                 result[i_n1 + i_n2] += carry;
     56 
     57             /* 在num1中的每个数字重复后向左移动位置 */
     58             i_n1++;
     59         }
     60 
     61         /* 忽略最右边的0 */
     62         int i = result.length - 1;
     63         while (i >= 0 && result[i] == 0)
     64             i--;
     65 
     66         /* 如果全部为'0', 表示num1或num2两者之一为'0'或者都为0 */
     67         if (i == -1)
     68             return "0";
     69 
     70         /* 生成结果字符串 */
     71         StringBuilder s = new StringBuilder();
     72         while (i >= 0) {
     73             s.append(result[i--]);
     74         }
     75 
     76         return s.toString();
     77     }
     78 
     79     public static void main(String[] args) {
     80         String str1 = "-1235421415454545454545454544";
     81         String str2 = "-1714546546546545454544548544544545";
     82 
     83         // String str1 = "1234";
     84         // String str2 = "5678";
     85 
     86         if (str1.charAt(0) == '-' &&
     87                 str2.charAt(0) != '-')
     88         {
     89             str1 = str1.substring(1);
     90             System.out.println("-");
     91         }
     92         else if (str1.charAt(0) != '-' &&
     93                 str2.charAt(0) == '-')
     94         {
     95             str2 = str2.substring(1);
     96             System.out.println("-");
     97         }
     98         else if (str1.charAt(0) == '-' &&
     99                 str2.charAt(0) == '-')
    100         {
    101             str1 = str1.substring(1);
    102             str2 = str2.substring(1);
    103         }
    104         /*
    105             result:            2118187521397235888154583183918321221520083884298838480662480
    106             copy from console: 2118187521397235888154583183918321221520083884298838480662480
    107          */
    108         System.out.println(multiply(str1, str2));
    109 
    110     }
    111 }
  • 相关阅读:
    深入浅出Redis(三)高级特性:管道
    CxImage的编译及简单使用举例
    [Zlib]_[0基础]_[使用zlib库压缩文件]
    java 实现打印当前月份的日历
    hdu 5087 Revenge of LIS II ( LIS ,第二长子序列)
    spring理解一
    poj 3181 Dollar Dayz (整数划分问题---递归+DP)
    android键盘事件
    Linux编程环境介绍(2) -- shell(Bash) 介绍
    iphone开发中数据持久化之——嵌入式SQLite(三)
  • 原文地址:https://www.cnblogs.com/magic-sea/p/12032047.html
Copyright © 2011-2022 走看看