递归与分治策略之大整数的乘法

来源:互联网 发布:手机上怎样改淘宝评价 编辑:程序博客网 时间:2024/06/11 03:17

题目描述

计算两个长度小于100位的大整数的乘积。
例如:
输入:
111111111
222222222
输出:
24691357975308642

解题思路一-利用小学学过的思路

我们小学学过的思路是什么呢?
举个例子,比如我们在计算 48*32的时候是这样计算的:
小学方法

在有了这样的思路之后,我们就开始用这种思路进行编程啦!

#include<stdio.h>#include<string.h>#define MAX_LEN 200char strArray1[MAX_LEN+5];char strArray2[MAX_LEN+5];int an1[ MAX_LEN + 5 ]={0};int an2[ MAX_LEN + 5 ]={0};int aResult[ MAX_LEN * 2 + 10 ]={0};int arrayLen1;int arrayLen2;int main(){    //输入两个数    gets(strArray1);    gets(strArray2);    arrayLen1=strlen(strArray1);    arrayLen2=strlen(strArray2);    for(int i=0;i<arrayLen1;i++){        intArray1[arrayLen1-i-1]=strArray1[i]-'0';    }    for(int i=0;i<arrayLen2;i++){        intArray2[arrayLen2-i-1]=strArray2[i]-'0';    }    for(int i=0;i<arrayLen1;i++){        for(int j=0;j<arrayLen2;j++){            resultArray[i+j]+=intArray1[i]*intArray2[j];    //先不进行进位1处理         }    }    for(int i=0;i<MAX_LEN*2;i++){//进行进位1处理         if(resultArray[i]>10){            resultArray[i+1]+=resultArray[i]/10;            resultArray[i]%=10;        }    }    int flag=0; //  标记哪一位开始不是0     for(int i=MAX_LEN*2;i>=0;i--){        if(flag!=0){            printf("%d",resultArray[i]);        }else if(resultArray[i]!=0){            flag=1; //标记找到了最高位             printf("%d",resultArray[i]);        }    }    //如果结果全0    if(flag==0){        printf("0");    } }

以上就是按照这种简单的思路一步一步来计算的,时间复杂度是O(n2)
但是今天我们讲的是递归与分治啊,那么又该怎么去解决这个问题呢?

解题思路二-分治与递归

那么大致的思路是怎样的呢?就以 2481*43659为例吧:

递归分治算法

从上面的图中我们可以的到:
在假设X和Y的长度分别为 l1 和 l2 的情况下,有:

XY=AC10l1/2+l2/2+AD10l1/2+BC10l2/2+BD

我们利用上面的结论,得到如下的代码:

#include<stdio.h>#include<string.h>#include<stdlib.h>#define MAX_LEN 200char strArray1[MAX_LEN+5];char strArray2[MAX_LEN+5];char resultArray[MAX_LEN*2+10];int arrayLen1;int arrayLen2;char* left(char dst[],char src[], int n);char* right(char dst[],char src[], int n);char* add(char* num1,char* num2);char* mul(char* num1,char* num2);int convertToInt(char* src,int len){    int sum=0;    for(int i=0;i<len;i++){        sum*=10;        sum+=src[i]-'0';    }    return sum;}char* convertToCharPoint(int num,int len){    char *a=(char*)calloc(len+1,sizeof(char));;    for(int i=0;i<len;i++){        int temp=num%10;        num/=10;        a[len-i-1]=temp+'0';    }//  a[len]='\0';    return a;}char* divideConquer(char array1[],char array2[]){//  printf("传入数据=%s %s\n",array1,array2);    int arr1Len=strlen(array1);    int arr2Len=strlen(array2);//  printf("长度1=%d %d\n",arr1Len-arr1Len/2,arr1Len/2);//  printf("长度2=%d %d\n",arr2Len-arr2Len/2,arr2Len/2);    if(arr1Len==1){     //设置第二位为位数较小位         char* result=mul(array2,array1);        return result;    }else if(arr2Len==1){        char* result=mul(array1,array2);        return result;    }    char *tempA=(char*)calloc(arr1Len-arr1Len/2,sizeof(char));    char *tempB=(char*)calloc(arr1Len/2,sizeof(char));    char *tempC=(char*)calloc(arr2Len-arr2Len/2,sizeof(char));    char *tempD=(char*)calloc(arr2Len/2,sizeof(char));    strncpy(tempA,array1,arr1Len-arr1Len/2);//  printf("==%s\n",array1+arr1Len-arr1Len/2);    strncpy(tempB,array1+arr1Len-arr1Len/2,arr1Len/2);    strncpy(tempC,array2,arr2Len-arr2Len/2);    strncpy(tempD,array2+arr2Len-arr2Len/2,arr2Len/2);//  tempA[arr1Len-arr1Len/2]='\0';//  tempB[arr1Len/2]='\0';//  tempC[arr2Len-arr2Len/2]='\0';//  tempB[arr2Len/2]='\0';//  printf("=##=%c %c \n",tempB[0],tempB[1]);//  printf("切分后=%s %s %s %s\n",tempA,tempB,tempC,tempD);/// printf("%d %d %d %d\n",strlen(tempA),strlen(tempB),strlen(tempC),strlen(tempD));    char* AC=divideConquer(tempA,tempC);    char* AD=divideConquer(tempA,tempD);    char* BC=divideConquer(tempB,tempC);    char* BD=divideConquer(tempB,tempD); // printf("计算结果后=%s %s %s %s\n",AC,AD,BC,BD);    //AC     int l1=arr1Len/2;    int l2=arr2Len/2; // printf("长度=%d %d\n",l1,l2);    char* resultAC=(char*)calloc(strlen(AC)+l1+l2,sizeof(char));    int i;    for ( i = 0; i < strlen(AC)+l1+l2; i++) {        if(i<strlen(AC)) resultAC[i]=AC[i];        else resultAC[i]=48;    }    resultAC[i]='\0';//  printf("AC=%s\n",resultAC);    //AD    char* resultAD=(char*)calloc(strlen(AD)+l1,sizeof(char));    for ( i = 0; i < strlen(AD)+l1; i++) {        if(i<strlen(AD)) resultAD[i]=AD[i];        else resultAD[i]=48;    }    resultAD[i]='\0';//  printf("AD=%s\n",resultAD);    //BC    char resultBC[MAX_LEN+5];    for ( i = 0; i < strlen(BC)+l2; i++) {        if(i<strlen(BC)) {            resultBC[i]=BC[i];        }        else resultBC[i]=48;    }    resultBC[i]='\0'; // printf("total=%s %s %s %s\n",resultAC,resultAD,resultBC,BD);    char* result=add(resultAC,resultAD);    result=add(result,resultBC);    result=add(result,BD);    free(tempA);     free(tempB);     free(tempC);     free(tempD);     free(resultAC);     free(resultAD);     free(AC);     free(AD);     free(BC);     free(BD);     return result;}char* add(char* num1,char* num2){//num1长度>num2     int num1Len=strlen(num1);    int num2Len=strlen(num2);//  printf("%d %d\n",num1Len,num1Len);     char result[MAX_LEN*2+10]={0};    for(int i=0;i<num2Len;i++){        result[i]+=num2[num2Len-i-1]+num1[num1Len-i-1]-'0';//        if(result[i]-48>=10){            result[i]-=10;            result[i+1]+=1;        }    }    for(int i=num2Len;i<num1Len;i++){        result[i]+=num1[num1Len-i-1];        if(result[i]-'0'>=10){            result[i]-=10;            result[i+1]+=1;        }    }    int length=0;    for(int i=MAX_LEN*2+9;i>=0;i--){        if(result[i]!=0){            length=i+1;            if(result[i]==1){                result[i]+=48;            }            break;        }    }    char* dst=(char*)calloc(length,sizeof(char));    for(int i=0;i<length;i++){        dst[i]=result[length-i-1];    }    dst[length]='\0';  //   printf("[%s+%s=%s]\n",num1,num2,dst);    return dst;}char* mul(char* num1,char* num2){//num2的长度为一位     int num1Len=strlen(num1);    int num2Len=strlen(num2);   //num2Len的值为1 //  printf("%d %d\n",num1Len,num1Len);     char result[MAX_LEN*2+10]={0};    for(int i=0;i<num1Len;i++){        result[i]+=(num1[num1Len-i-1]-'0')*(num2[0]-'0')+'0';//        if(result[i]-48>=10){            result[i]-=10;            result[i+1]+=1;        }    }    int length=0;    for(int i=MAX_LEN*2+9;i>=0;i--){        if(result[i]!=0){            length=i+1;            if(result[i]==1){                result[i]+=48;            }            break;        }    }    char* dst=(char*)calloc(length,sizeof(char));    for(int i=0;i<length;i++){        dst[i]=result[length-i-1];    }    dst[length]='\0';     //printf("[%s+%s=%s]\n",num1,num2,dst);    return dst;}int main(){    //输入两个数    gets(strArray1);    gets(strArray2);    arrayLen1=strlen(strArray1);    arrayLen2=strlen(strArray2);    char* resultArray=divideConquer(strArray1,strArray2);    printf("%s",resultArray);}

利用Master定理也可以知道该算法的时间复杂度为 O(n2)

最后

最后1,把你的代码提交到OJ上面试试看能否AC吧!
http://poj.org/problem?id=2389