Find the Closest Palindrome:寻找与给定目标大小最接近且尽可能小的回文

本文介绍了一种寻找给定整数最接近的回文数的方法。通过将输入数字的前半部分翻转并与原始数字进行比较,算法能够找到绝对差最小的回文数。文章详细解释了处理特殊情况的步骤,并提供了完整的实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Given an integer n, find the closest integer (not including itself), which is a palindrome.

The 'closest' is defined as absolute difference minimized between two integers.

Example 1:

Input: "123"
Output: "121"

Note:

  1. The input n is a positive integer represented by string, whose length will not exceed 18.
  2. If there is a tie, return the smaller one as answer.


思路:对于123这种普通数字,从中折半取前半段,再反转过来,如12|3,取12,因为是奇数,所以翻折成121(若是偶数如1|2,就翻折成11)。

难点在于:10,100,200这种有可能向下取,也有可能向上取。

如10,答案应该是9。

100->99。

200->202。

所以考虑把前半段分别+1和-1,在翻折,结合最开始直接翻折,比较选出最合适的答案。

如10:

a.直接处理 1|0 ->11

b.前半段+1 2|0 ->22

c. 前半段-1  9| _  -> 9 (这里情况特殊。,因为-1后为0,所以直接将0替换成9)

如100:

a.直接处理  10|0 ->101

b.前半段+1  11|0 ->111

c. 前半段-1  9|0  -> 99

关于翻折,就是取前半段然后反转。如果长度是奇数,则正中间不动,将剩余前半段逆序然后连接上,如果长度为偶数,则直接将前半段逆序在连接上。


以上过程可以参见:https://leetcode.com/problems/find-the-closest-palindrome/solution/


class Solution {
	public String mirror(String n) {
		String sub = n.substring(0, n.length() / 2);
		return sub + (n.length() % 2 == 1 ? n.charAt(n.length() / 2) : "")
				+ (new StringBuilder(sub).reverse().toString());
	}

	public String nearestPalindromic(String n) {
		if(n.length()==1) return (Integer.parseInt(n) - 1) + "";//针对0,1,2,3..,9这几种长度为1的情况
		
		// 翻折版本
		long diff1 = 0;
		String r1 = mirror(n);
		diff1 = Math.abs(Long.parseLong(n) - Long.parseLong(r1));
		if(diff1==0) diff1 = Long.MAX_VALUE;//不能出现自身这种情况,题目中明确要求
		// 针对100->99这种情况,折半减去1
		long diff2 = 0;
		//注意:此处极容易错,会把10返回11,而不是9,因为当奇数时把中间位置忽略了,对于n=10,s1=11而使s2变为00,s3=22而错误!!
		int i = (n.length() -1)/ 2 ;	//注意此处是n.length() -1/ 2,千万不是n.length() / 2 - 1!!!!!!!因为要把奇数时中间的那位也算上
		StringBuilder s = new StringBuilder(n);
		while (i >= 0 && s.charAt(i) == '0') {
			s.replace(i, i + 1, "9");
			i--;
		}		
		if (i == 0 && s.charAt(i) == '1') {
			s.delete(i, i + 1);
			//针对10这种情况,如果不补充删除1后s变成0,那么最后结果s2为0
			s.replace(((s.length() -1)/ 2), ((s.length() -1)/ 2+1), "9");
		} else {
			s.replace(i, i + 1, (char) (s.charAt(i) - 1) + "");
		}
		String r2 = mirror(s.toString());
		diff2 = Math.abs(Long.parseLong(n) - Long.parseLong(r2));

		// 针对200->202这种情况,折半加上1
		long diff3 = 0;
		int x = (n.length() -1) / 2 ;
		System.out.println("x: "+x);
		s = new StringBuilder(n);
		while (x >= 0 && s.charAt(x) == '9') {
			s.replace(x, x + 1, "0");
			x--;
		}
		if (x < 0) {//注意此处是x<0,因为是要填充,与上面的diff2不同
			s.insert(0, '1');
		} else {
			s.replace(x, x + 1, (char) (s.charAt(x) + 1) + "");
		}
		String r3 = mirror(s.toString());
		diff3 = Math.abs(Long.parseLong(n) - Long.parseLong(r3));
		System.out.println("s1,s2,s3 "+r1+" "+r2+" "+r3);
		if (diff2 <= diff1 && diff2 <= diff3)
			return r2;
		if (diff1 <= diff3 && diff1 <= diff2)
			return r1;
		else
			return r3;
	}
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值