Code Ganker: Multiply Strings -- LeetCode

2014年3月10日星期一

Multiply Strings -- LeetCode

原题链接: http://oj.leetcode.com/problems/multiply-strings/
这道题属于数值操作的题目,其实更多地是考察乘法运算的本质。基本思路是和加法运算还是近似的,只是进位和结果长度复杂一些。我们仍然是从低位到高位对每一位进行计算,假设第一个数长度是n,第二个数长度是m,我们知道结果长度为m+n或者m+n-1(没有进位的情况)。对于某一位i,要计算这个位上的数字,我们需要对所有能组合出这一位结果的位进行乘法,即第1位和第i位,第2位和第i-1位,... ,然后累加起来,最后我们取个位上的数值,然后剩下的作为进位放到下一轮循环中。这个算法两层循环,每层循环次数是O(m+n),所以时间复杂度是O((m+n)^2)。算法中不需要额外空间,只需要维护一个进位变量即可,所以空间复杂度是O(1)。代码如下:
public String multiply(String num1, String num2) {
    if(num1 == null || num2 == null || num1.length()==0 || num2.length()==0)
        return "";
    if(num1.charAt(0)=='0')
        return "0";
    if(num2.charAt(0)=='0')
        return "0";
    StringBuilder res = new StringBuilder();
    int num = 0;
    for(int i=num1.length()+num2.length();i>0;i--)
    {
        for(int j=Math.min(i-1,num1.length());j>0;j--)
        {
            if(i-j<=num2.length())
            {
                num += (int)(num1.charAt(j-1)-'0')*(int)(num2.charAt(i-1-j)-'0');
            }
        }
        if(i!=1 || num>0)
            res.append(num%10);
        num = num/10;
    }
    return res.reverse().toString();
}
实现中有两个小细节,一个是循环中最后有一个if判断,其实就是看最高一位是不是0(最高第二位不可能是0,除非两个源字符串最高位带有0),如果是就不需要加入字符串中了。另一个小问题是我们是由低位到高位放入结果串的,所以最后要进行一次reverse,因为是一个O(m+n)的操作,不会影响算法复杂度。
这道题其实还有更加优的做法,就是用十大最牛的算法之一--Fast Fourier transform(FFT)。使用FFT可以在O(nlogn)时间内求出多项式的乘法,在这里只需要把变量x带入10,然后按照求多项式的方法就可以求出两个大整数的成绩了。想了解细节的朋友搜一下快速傅里叶变换求多项式乘积就可以找到相关资料了,是比较成熟的算法。不过FFT实现不是很简单,所以在面试中一般不需要写代码,只需要知道这个思路和基本工作原理就可以了哈。

没有评论:

发表评论