• 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。

  • 相关阅读:
    基于SOA分布式架构的dubbo框架基础学习篇
    项目管理 绩效考核
    性能测试晋级教程
    从页面走向单元实现真正的业务驱动
    微软的开源Sonar工具测试网站的性能和安全性
    2.动手实操Apache ZooKeeper
    1. Apache ZooKeeper快速课程入门
    开发人员的福音:微软、谷歌、Mozilla将他们所有的Web API文档放在同一个地方
    Happy Java:定义泛型参数的方法
    比较两个文件不同以及生成SQL插入语句
  • 原文地址:https://www.cnblogs.com/chenjx85/p/9159043.html
Copyright © 2020-2023  润新知