1,明确程序是一个通用法则。这个实现过程既可以满足一位数字相乘,也可以满足两位数字相乘。既然能够满足一位数字,两位数字,那么自然也能够满足多位数字相乘。
2,最开始自己面对这一道面试题,第一反应就是,我无法使用任何编程语言的基本数据类型去表示这样一个大数,自然也不能够满足这个数的乘积了。这也是这个面试题的难点。
3,我的想法就是抛开一切数学中的理论概念。用编程语言的字符组成字符串的方式进行思考。
4,思考了很久。也按照自己的想法分析这个大数的一些特征,比如大数的个数是明确的。我可以任意按照自己的想法去取。去拼接最后的一个结果。但是都没有想到一个解决思路。当然问题肯定能够解决的,只是会显得特别复杂,这样程序的易读性也就没有了。
5,网上搜寻资料。得到一个解决问题的思想。
思想:将输入的字符串,转成char数组,转成int数组。采用分治思想,每一位的相乘。
公式:AB*CD = AC (BC+ AD) BD,然后 从后到前满十进位。
举个例子
套用公式
67*89 = 6*8(7*8 + 6*9)7*9
67*89 = 48(110)63
从后到前满十进位
63进6剩余3,
110变成116,满十进位,进行11,剩余6,
48变成59。所以: 5963
6,实现过程
publicString multiply(String num1, String num2) {
//把字符串转成char数组
charchars1[] = num1.toCharArray();
charchars2[] = num2.toCharArray();
//声明存放结果和两个乘积的容器
intresult[] = newint[chars1.length + chars2.length];
int n1[]= newint[chars1.length];
int n2[]= newint[chars2.length];
//把char转换成int数组。
for (int i =0; i < chars1.length; i++){
n1[i] = chars1[i] - '0';
}
for (int j =0; j < chars2.length; j++){
n2[j] = chars2[j] - '0';
}
//逐个相乘
for (int i = 0; i < chars1.length; i++){
for (int j = 0; j < chars2.length; j++) {
result[i+j] += n1[i] * n2[j];
}
}
//从后往前满十进位
for (int i = result.length -1; i > 0; i--) {
result[i-1] += result[i] / 10;
result[i] = result[i] % 10;
}
//转成string并返回
String resultStr = "";
for (int i = 0; i < result.length - 1; i++) {
resultStr += "" +result[i];
}
returnresultStr;
}7,关键点
a,一个数乘以一个数的结果长度必定小于或者等于这个两个数长度之和。
b,把char字符转成int型,需要这个字符减去字符0.
字符和数字在内存里都是以ASCII形式存储的。'0'字符的ASCII是30。
c,逐个相乘。(其实也是数组中根据index的对应位上进行相加累积)
算法是根据数据结构的。而我们的数据是放入数组中进行操作的。我怎样才能操作两个数据结构(数组)的每一位呢?刚接触编程的时候,通常会学习冒泡排序和选择排序,通过两层循环去遍历这个数据结构中的每一个数字(一般来说都是多位的)。并且这种基本算法思想,在实现业务逻辑过程中也是需要的,可见对基本知识的一个理解深度是很重要的。
d,从后往前满十进位。一个操作。
关键
哪个位是进位并且作相加累积。
哪个位是保存余下的数字。
图解循环过程
从后往前满十进位
21,进2,剩下1;
32+2为34,进3,剩下4;
34+3为37,进行3,剩下7;
28+3为31,进3,剩下1;
13+3为16,进1,剩下6;
4+1为5。所以:561741。