一、题目
二、思路(自己)
- 题目要求两个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;
}
}
- 官方构造回文数是从最大的回文数开始,然后一直减的。
四、一些题外话
很久没更新了,大概有个二十天吧,主要是因为断更那天发生了一件比较倒霉的事,导致我不得不停更这么久。现在慢慢恢复,我会一直加油更新下去的!胡逸杰冲冲冲