Nearest Palindrome
XXX. Nearest Palindromic Number
Mathematics
String Manipulation
Problem Statement:
Given a string n
representing a positive integer, find the closest integer (not including itself) which is a palindrome. The result should be returned as a string.
If there is a tie, return the smaller integer.
Algorithm:
-
Identify the first half of the input string
n
, which can be used to generate potential palindrome candidates by mirroring. -
Generate the following candidates:
- Palindrome by mirroring the first half.
- Palindrome by mirroring the first half incremented by 1.
- Palindrome by mirroring the first half decremented by 1.
- The largest palindrome smaller than
n
, such as999...999
. - The smallest palindrome larger than
n
, such as100...001
.
-
Compare all candidates with
n
and select the one with the smallest absolute difference. If there is a tie, choose the smaller numerical value.
Complexity:
Time Complexity: O(k), where k
is the length of the input string n
, for generating candidates and comparing them.
Space Complexity: O(1), ignoring the space required for storing the result.
Java Implementation:
class Solution {
public String nearestPalindromic(String n) {
int len = n.length();
int i = len % 2 == 0 ? len / 2 - 1 : len / 2;
long firstHalf = Long.parseLong(n.substring(0, i + 1));
// Generate possible palindromic candidates
List possibilities = new ArrayList<>();
possibilities.add(halfToPalindrome(firstHalf, len % 2 == 0));
possibilities.add(halfToPalindrome(firstHalf + 1, len % 2 == 0));
possibilities.add(halfToPalindrome(firstHalf - 1, len % 2 == 0));
possibilities.add((long) Math.pow(10, len - 1) - 1); // Smallest n-digit palindrome
possibilities.add((long) Math.pow(10, len) + 1); // Largest n-digit palindrome
// Find the closest palindrome
long diff = Long.MAX_VALUE, res = 0, num = Long.parseLong(n);
for (long candidate : possibilities) {
if (candidate == num) continue; // Skip the number itself
if (Math.abs(candidate - num) < diff || (Math.abs(candidate - num) == diff && candidate < res)) {
diff = Math.abs(candidate - num);
res = candidate;
}
}
return String.valueOf(res);
}
private long halfToPalindrome(long left, boolean even) {
long res = left;
if (!even) left /= 10; // For odd-length, skip the middle digit
while (left > 0) {
res = res * 10 + (left % 10); // Append reversed digits to form palindrome
left /= 10;
}
return res;
}
}