leetcode-479-Largest Palindrome Product(找到两个乘数相乘得到的最大的回文数)

题目描述:

Find the largest palindrome made from the product of two n-digit numbers.

Since the result could be very large, you should return the largest palindrome mod 1337.

Example:

Input: 2

Output: 987

Explanation: 99 x 91 = 9009, 9009 % 1337 = 987

 

Note:

The range of n is [1,8].

 

要完成的函数:

int largestPalindrome(int n) 

说明:

1、给定一个数字n,我们可以形成一个n位的数字(十进制),比如n=2,那么我们可以形成99或者98或者12这些两位的数字。

要求从两个n位的数字的积中找到最大的回文数,比如n=2,那么我们可以形成99/99这两个2位的数字,然后积是9801,不是回文数,那么我们就要继续往下找,99*98=9702,也不是……一直往下找,直到99*91=9009这个回文数。

由于回文数数值比较大,所以我们返回回文数%1337的结果就好。

2、这道题传统解法是找到n位数字的最大可能值和最小可能值,比如n=2,那么上限就是99,下限就是10,然后在上下限之间的数字彼此相乘,逐个判断是否为回文数。

这种方法也能解出来,不过就是很慢。

你得找出所有数字相乘得到的积,然后一个个判断是否是回文数。

但找出所有数字相乘得到的积,不能像下面这样写:

    bool ishuiwen(long t)
    {
        long result=0,t1=t;
        while(t!=0)//得到反转之后的数,存储在result中
        {
            result=result*10+t%10;
            t/=10;
        }
        return result==t1;
    }
    int largestPalindrome(int n) 
    {
        if(n==1) 
            return 9;
        int uplim=pow(10,n)-1,lowlim=pow(10,n-1);
        long t;
        for(long i=uplim;i>=lowlim;i--)//双重循环
        {
            for (long j=i;j>=lowlim;j--)
            {
                t=i*j;
                if(ishuiwen(t))
                    return t%1337;
            }
        }
    }    

上面这样写会出错的,因为双重循环从最开始的 i = 99,然后 j 一直减小,直到 i 和 j 相乘的结果是一个回文数,假设是99*55。但可能还有一个更大的回文数,假设是98*89这种,而98*89这个结果根本不会被计算出来,我们算到99*55就return了。

我们用双重循环的话,得计算出所有相乘的结果,然后一个个判断是否是回文数,最后返回最大的那个。

这样做太慢了。

我们尝试一下生成法,生成所有可能的回文数,然后逐个判断是否是上下限之间的数相乘的结果。这样能大大减少需要判断的个数,而且判断的过程就是判断能不能整除,非常快速。

代码如下:(附详解)

    long buildhuiwen(int n)//建立回文数 
    {
        long n1=n,result=0;
        while(n!=0)
        {
            result=result*10+n%10;
            n/=10;
            n1*=10;
        }
        return n1+result;
        
    }
    int largestPalindrome(int n) 
    {
        if(n==1) 
            return 9;
        int uplim=pow(10,n)-1,lowlim=pow(10,n-1);//得到上限是uplim,下限是lowlim
        for(int i=uplim;i>=lowlim;i--) 
        {
            long cand=buildhuiwen(i);//建立2n位的回文数,比如i=99,那么建立的回文数是9999,比如i=98,建立的回文数9889,构造回文序列。
            for (long j=uplim;j*j>=cand;j--)//判断得到的回文数是否能整除n位的数字
            {
                if(cand%j==0)
                    return cand%1337;
            }
        }
    }

上述代码中的外层循环,构造了一个回文序列,如果n=2,那么构造的回文序列是9999,9889,9779,9669,9559,9449……

接着在内层循环中,判断构造的每一个回文数是否能整除n位数。

这样做快了很多,减少了要判断的个数,而且判断过程也简化了,只需要判断是否整除。

细心的同学可能会发现,内层循环中的long j=uplim;j*j>=cand;j--,c++支持大数乘法了……

之前c++11没出的时候,大数乘法和加法都是要手工写代码实现的,现在不用啦。

上述代码实测366ms,beats 86.19% of cpp submissions。

猜你喜欢

转载自www.cnblogs.com/king-3/p/9159043.html