Given two numbers represented as strings, return multiplication of the numbers as a string.
Note:
- The numbers can be arbitrarily large and are non-negative.
- Converting the input string to integer is NOT allowed.
- You should NOT use internal library such as BigInteger.
这道题求的大数乘法,不允许用BigInteger并且不允许将num1和num2转换成int类型。
当然数据非常大,就算把num1和num2转换成int也会溢出。
虽然不允许使用BigInteger,但是可以回忆一下BigInteger。
刚开始使用了双StringBuilder,一个来存储最终结果,一个来存储每一次的乘法结果,虽然AC,但是成绩很差。
public class Solution {
public String multiply(String num1, String num2) {
int len1 = num1.length();
int len2 = num2.length();
if( len1 > len2)
return multiply(num2,num1);
StringBuilder result = new StringBuilder();
StringBuilder num ;
int aa = 0, bb = 0, pos = 0;
for( int i = len1-1; i>=0;i--){
if( num1.charAt(i) == 0)
continue;
aa = 0;
num = new StringBuilder();
for( int j = len2-1; j>=0 ; j--){
if( num1.charAt(i) == 1){
num.append(num2);
break;
}
num.insert(0,((num2.charAt(j)-'0')*(num1.charAt(i)-'0')+aa)%10);
aa = ((num2.charAt(j)-'0')*(num1.charAt(i)-'0')+aa)/10;
}
if(aa > 0)
num.insert(0, aa);
bb = 0;
for( int k = num.length()-1 ; k>=0;k--){
pos = num.length()-k+len1-2-i;//从右往左数第pos位
pos = result.length()-1 - pos;//第pos位
if( pos < 0 ){
while( pos < 0 ){
result.insert(0, num.charAt(k)-'0'+bb);
bb = 0;
pos++;
}
}
else{
int cc = (num.charAt(k)-'0') + (result.charAt(pos)-'0') + bb;
result.replace(pos, pos+1, String.valueOf(cc%10));
bb = cc/10;
}
}
if( bb > 0){
if( pos == 0 )
result.insert(0, String.valueOf(bb));
else if( pos > 0)
result.replace(pos-1, pos, String.valueOf(result.charAt(pos-1)-'0'+bb));
}
}
for( int i = 0; i< result.length() ; i++){
if( result.charAt(i) == '0'){
result.delete(i,i+1);
i--;
}else
break;
}
if( result.length() == 0)
return "0";
return result.toString();
}
}
然后将StringBuilder转变成int[]:
1。因为一个n位数与一个m位数相乘,最多为m+n位数
2。另一个n位数同样的与一个一位数相乘。那么最多为n+1位数。
这样做避免了对对象的多次操作,提高了速度,但是结果仍旧不是很理想。
public class Solution {
public String multiply(String num1, String num2) {
int len1 = num1.length();
int len2 = num2.length();
if (len1 > len2)
return multiply(num2, num1);
int[] res = new int[len1+len2];
int pos = 0, aa =0;
for( int i =len1-1; i>=0;i--){
if (num1.charAt(i) == '0')
continue;
aa = 0;
for( int j = len2-1; j>=0; j--){
pos = j+1+i;
int mi = (num2.charAt(j) - '0')*(num1.charAt(i) - '0') + aa + res[pos];
res[pos] = mi%10;
aa = mi/10;
}
if (aa > 0)
res[pos-1] =res[pos-1]+ aa;
}
StringBuilder result = new StringBuilder();
for (int i = 0; i < res.length; i++) {
if( !(res[i] == 0 && result.length() == 0))
result.append(res[i]);
}
if( result.length() == 0)
return "0";
return result.toString();
}
}
最后在查找了资料发现,jvm启动时间影响太大,同样的代码运行的时间也会不一样,因此不再纠结于代码速度达到最快。
相比于上一次,最后还是有了一些微调,主要就是进位的操作放在最后一次进行,这大量减少了操作次数,也就提高了运行时间。
public class Solution {
public static String multiply(String num1, String num2) {
int len1 = num1.length() ,len2 = num2.length();
int[] Num2 = ToInt(num2);
int[] res = new int[len1+len2];
for( int i =len1-1; i>=0;i--){
add(num1.charAt(i)-'0',Num2,res,i);
}
for( int i = len1+len2-1,b = 0;i>=0;i--){
int a = res[i] + b;
res[i] = a%10;
b = a/10;
}
StringBuilder result = new StringBuilder();
for(int i = 0;i< res.length;i++){
if( res[i]!= 0 ){
while( i<res.length){
result.append(res[i]);
i++;
}
}
}
if( result.length() == 0)
return "0";
return result.toString();
}
public static void add(int num,int[] num1,int[] res,int pos){
for( int i =num1.length-1 ; i >=0;i--){
res[i+pos+1] += num*num1[i];
}
}
public static int[] ToInt(String num){
int[] res = new int[num.length()];
for( int i =0;i<num.length(); i++){
res[i] = num.charAt(i)-'0';
}
return res;
}
}