大数相乘
近期看的算法比较杂,在博客上简单记录一下吧。大数相乘貌似在很多公司的面试中都有问过。
问题描述:
输入两个整数,要求输出这两个数的乘积。输入的数字可能超过计算机内整形数据的存储范围。
乘数A和B分别存放在字符串里,输出结果也存放在字符串中。
问题分析:
首先,考虑类似0000000123456789这样数字输入,为了避免不必要的计算,可以对输入字符串进行预处理preProcess,把前缀为0的字符串简化为从第一个不为零的数字开始的字符串。
其次,考虑输出字符串的长度,假设A的长度为a,B的长度为b,则两者相乘的长度为a + b - 1或者a + b。
第三,注意char和int之间的相互转化,char c转int a的方法:a = c - '0'或 a = c - 48,int a转char c的方法:c = (char) (a + 48)
然后,每次用一个数的一位与另一个数从低至高依次相乘,并与结果上的该位相加,动态更新结果。这个过程需要有addFlag和multiFlag来记录上次运算的加法进位和乘法进位。
最后,同样使用preProcess将结果最高位的0去掉。
public class Multiple { public String multiple(String A, String B) { String A1 = preProcess(A); String B1 = preProcess(B); char[] c1 = A1.toCharArray(); char[] c2 = B1.toCharArray(); char[] rst = new char[c1.length + c2.length]; for (int i = 0; i < rst.length; i++) { rst[i] = '0'; } reverse(c1, 0, c1.length - 1); reverse(c2, 0, c2.length - 1); for (int i = 0; i < c1.length; i++) { int addFlag = 0; int multiFlag = 0; for (int j = 0; j < c2.length; j++) { int temp1 = (c1[i] - 48) * (c2[j] - 48) + multiFlag; multiFlag = temp1 / 10; temp1 = temp1 % 10; int temp2 = rst[i + j] - 48 + temp1 + addFlag; addFlag = temp2 / 10; rst[i + j] = (char) (temp2 % 10 + 48); } rst[i + c2.length] = (char) (addFlag + multiFlag + 48); } reverse(rst, 0, rst.length - 1); return preProcess(new String(rst)); } public void reverse(char[] c, int start, int end) { while (start < end) { char temp = c[start]; c[start] = c[end]; c[end] = temp; start++; end--; } } public String preProcess(String s) { char[] c = s.toCharArray(); int i = 0; while (i < c.length) { if (c[i] == '0') { i++; continue; } else { break; } } if (i == c.length) { return new String("0"); } return new String(c, i, c.length - i); } }
test case试过了“0000”*“00”,“999999”*“99”,“0011”*“01”这样的边界case,都没有问题。
这里的乘法默认是非负数相乘,若为负数相乘,只需要预先判断第一位,最后在结果加上相应符号即可。
posted on 2016-12-19 18:13 ShinningWu 阅读(267) 评论(0) 编辑 收藏 举报