题目来源:https://leetcode-cn.com/problems/find-the-closest-palindrome/
大致题意:
给一个字符串表示的整数 n,以字符串形式返回与 n 之间差值最小的回文数(不能为其本身,有多个答案返回最小的)
思路
若要构造与原数差别尽可能小的回文数,可以直接将原数高位部分翻转替换低位部分,如 12345,取出高位 12,翻转为 21,替换低位 45,结果为 12321
但是这样翻转不一定是离原数最近的回文数,如 86201,翻转为 86268,但是事实上回文数 86168 离原数更近。
可见,这种情况下,翻转后的数大于原数,但是最近的回文数可能是前半部分 862 - 1 = 861 翻转后的结果。
相似的,12399 直接翻转后为 12321,但是最近的回文数是 12421。
可见,这种情况下,翻转后的数小于原数,但是最近的回文数可能是前半部分 123 + 1 = 124 翻转后的结果
但是只考虑将前半部分加 1、减 1和直接翻转 有时候也无法找到符合题意的最近回文数
- 如 1000,前半部分 10,减 1 翻转后为 99,加 1 翻转后为 1111,直接翻转为 1001。但是事实上最近回文数还有 999,小于 1001,所以 999 才是所求答案
- 如 999,减 1 翻转后为 989,加 1 翻转后为 10001,直接翻转为 999(为本身,不符合题意)。符合题意的最近回文数为 1001.
所以必须考虑前半部分加 1、减 1造成数的位数增加、减少的影响
- 可以通过每次将数对应长度位数减 1 的 99…99,和位数加 1 的 100…001放入候选的最近回文数避免这个问题
- 如原数 12345,位数为 5,那么就放入 9999(104 - 1)和 100001(105 + 1)
代码:
public class NearestPalindromic {
public String nearestPalindromic(String n) {
List<Long> candidates = getCandidates(n);
long num = Long.parseLong(n);
long ans = candidates.get(0);
long min = Math.abs(num - ans);
// 找出与原数的差值绝对值最小的数
for (int i = 1; i < candidates.size(); i++) {
if (candidates.get(i) == num) {
continue;
}
long cur = Math.abs(num - candidates.get(i));
if (cur < min) {
ans = candidates.get(i);
min = cur;
} else if (cur == min) {
ans = candidates.get(i) > ans ? ans : candidates.get(i);
}
}
return String.valueOf(ans);
}
public List<Long> getCandidates(String n) {
List<Long> candidates = new ArrayList<>();
int len = n.length();
// 中间位 +1 后可能导致位数增加,存下可能有的增位数
candidates.add((long) Math.pow(10, len) + 1);
// 中间位 -1 后可能导致位数减少,存下可能有的减位数
candidates.add((long) Math.pow(10, len - 1) - 1);
// 取数字的前一半
String prefix = n.substring(0, (len + 1) / 2);
long prefixNum = Long.parseLong(prefix);
// 遍历三种回文数,减少中间部分、中间部分不变、增加中间部分
for (long i = prefixNum - 1; i <= prefixNum + 1; i++) {
StringBuffer sb = new StringBuffer();
// 添加前半部分
sb.append(i);
StringBuffer suffix = new StringBuffer();
suffix.append(i).reverse();
// 添加后半部分
// 若原数字长度为奇数,那么后半部分要比前半部分长度 -1
sb.append(suffix.substring(len & 1));
candidates.add(Long.parseLong(sb.toString()));
}
return candidates;
}
}
该博客探讨了一种解决LeetCode问题——寻找给定整数的最近回文数的方法。通过分析如何翻转和调整数字的前半部分来生成可能的回文数,同时考虑了位数增加和减少的影响。文章详细解释了代码实现,包括获取可能的候选回文数的策略,并给出了具体的代码示例。

被折叠的 条评论
为什么被折叠?



