D46 LeetCode 479.最大回文数(困难)

一、题目

二、思路(自己)

  • 题目要求两个n位整数乘积的最大回文数,而n的取值范围是1~8,即输入的可能性只有八种,输出也只有八种。
  • 使用暴力破解法就是从n位数最大的相乘,直到得到的是回文数即可。
  • 暴力破解不可行,我想不出来,参考了一下评论区的解法。
  • 先求出两个n位数的最大乘积(2n位数),取前n位数作为初始值half,然后再通过其构造回文数。再检查能否由处于上界和下界之间的两个数相乘得到(怎么检查呢?也是一个难点,得降低复杂度)。如果不可以,half--,重新构造回文数,再次判断。(总感觉这题我在哪里做过呀)
    class Solution {
        public int largestPalindrome(int n) {
           if(n==1) return 9;
            //先求得half
            int num1=(int) Math.pow(10,n)-1;
            int half=num1*num1;
            for (;half>0;half--) {
                String s1=half+"";
                s1=s1.substring(0,n);
                StringBuilder s2=new StringBuilder(s1).reverse();
                String s3=s1+s2.toString();
                long ans=Long.parseLong(s3);
                for(int num2=num1;num2>(int)Math.sqrt(ans);num2--){
                    if(ans%num2==0) return (int)ans%1337;
                }
            }
            return -1;
        }
    }

    不懂时间复杂度为什么会超???我感觉跟下面这个解法差别不大呀

  • 用评论区的答案可以啊

    class Solution {
        public int largestPalindrome(int n) {
            if(n == 1){
                return 9;
            }
            long max = (long)Math.pow(10,n)-1;
            long min = (long)Math.pow(10,n-1);
            long half = max*max/(min*10);
            long val;
            long temp;
            while(true){
                val = getVal(half);
                for(long i = max ; i >= Math.sqrt(val) ; i--){
                    if(val % i == 0){
                        temp = val / i;
                        if(temp >= min && temp <= max){
                            return (int)(val % 1337);
                        }
                    }
                }
                half--;
            }
        }
    
        public long getVal(long half){
            StringBuilder sb = new StringBuilder();
            return Long.parseLong(half+sb.append(half).reverse().toString());
        }
    }

     

三、题解(官方)

官方构造回文数不是通过字符串反转,而是用数学知识

class Solution {
    public int largestPalindrome(int n) {
        if (n == 1) {
            return 9;
        }
        int upper = (int) Math.pow(10, n) - 1;
        int ans = 0;
        for (int left = upper; ans == 0; --left) { // 枚举回文数的左半部分
            long p = left;
            for (int x = left; x > 0; x /= 10) {
                p = p * 10 + x % 10; // 翻转左半部分到其自身末尾,构造回文数 p
            }
            for (long x = upper; x * x >= p; --x) {
                if (p % x == 0) { // x 是 p 的因子
                    ans = (int) (p % 1337);
                    break;
                }
            }
        }
        return ans;
    }
}
  • 官方构造回文数是从最大的回文数开始,然后一直减的。

四、一些题外话

很久没更新了,大概有个二十天吧,主要是因为断更那天发生了一件比较倒霉的事,导致我不得不停更这么久。现在慢慢恢复,我会一直加油更新下去的!胡逸杰冲冲冲

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值