递归与分治策略之大整数的乘法
来源:互联网 发布:手机上怎样改淘宝评价 编辑:程序博客网 时间: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"); } }
以上就是按照这种简单的思路一步一步来计算的,时间复杂度是
但是今天我们讲的是递归与分治啊,那么又该怎么去解决这个问题呢?
解题思路二-分治与递归
那么大致的思路是怎样的呢?就以 2481*43659为例吧:
从上面的图中我们可以的到:
在假设X和Y的长度分别为 l1 和 l2 的情况下,有:
我们利用上面的结论,得到如下的代码:
#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定理也可以知道该算法的时间复杂度为
最后
最后1,把你的代码提交到OJ上面试试看能否AC吧!
http://poj.org/problem?id=2389
阅读全文
0 0
- 递归与分治策略之大整数的乘法
- 递归分治-大整数乘法
- 递归与分治策略:Strassen矩阵乘法
- 大整数分治乘法
- 大整数乘法---分治
- 大整数乘法-分治
- 分治-大整数乘法
- 分治法 --- 大整数的乘法
- 大整数的乘法(分治法)
- 分治法 --- 大整数的乘法
- 大整数的乘法-分治法
- 大整数乘法(分治法)
- 分治算法-大整数乘法
- 大整数乘法 ------分治法
- 分治算法--大整数乘法
- 【分治算法】大整数乘法
- 递归与分治之整数划分
- 递归与分治策略之快速排序
- java集合系列01--ArrayList
- Android APP测试的日志文件抓取
- CJOJ 1070 【Uva】嵌套矩形
- leetcode 122. Best Time to Buy and Sell Stock II
- scala基础系列一
- 递归与分治策略之大整数的乘法
- 深入理解javascript原型和闭包(14)——从【自由变量】到【作用域链】
- [莫比乌斯反演+容斥+分块求和] BZOJ2301: [HAOI2011]Problem b
- static_cast、dynamic_cast、const_cast和reinterpret_cast总结
- 通过配置文件切换接口的实现类
- POJ
- Interaction System使用入门之瞬移(瞬间拥有波风水门的飞雷神之术)
- 深入理解javascript原型和闭包(15)——闭包
- Java基础教程38-异常-try-catch