Given a numeric string n, find the closest palindrome number such that the absolute difference between the palindrome and n is minimum. If there are multiple palindrome numbers with the same absolute difference, return the smaller one.
Examples:
Input: n = "9"
Output: "9"
Explanation: 9 itself is a palindrome number.Input: n = "489"
Output: "484"
Explanation: Closest palindrome numbers from 489 are 484 and 494. Since both have the same absolute difference, we return the smaller one, which is 484.Input: n = "1234"
Output: "1221"
Explanation: Closest palindrome numbers from 1234 are 1221 and 1331. Since 1221 is closer than 1331, we return 1221.
Table of Content
[Naive Approach] Using Brute Force Approach
The idea is to check numbers just smaller than n and just greater than n until we find a palindrome on both sides. The first palindrome found on each side is the closest palindrome in that direction.
We then compare their differences with n and return the closer one. If both have the same difference, we return the smaller palindrome.
- Start with smaller = n - 1 and larger = n + 1.
- Move downward from smaller until a palindrome is found.
- Move upward from larger until a palindrome is found.
- Calculate the absolute difference of both palindromes from n.
- Return the palindrome with the smaller difference.
- If both differences are equal, return the smaller palindrome.
#include <bits/stdc++.h>
using namespace std;
// Check whether a number is a palindrome
bool isPalindrome(string s)
{
int i = 0, j = s.size() - 1;
while (i < j)
{
if (s[i] != s[j])
return false;
i++;
j--;
}
return true;
}
// Add 1 to a numeric string
string addOne(string s)
{
int i = s.size() - 1;
while (i >= 0 && s[i] == '9')
{
s[i] = '0';
i--;
}
if (i < 0)
return "1" + s;
s[i]++;
return s;
}
// Subtract 1 from a numeric string
string subtractOne(string s)
{
int i = s.size() - 1;
while (i >= 0 && s[i] == '0')
{
s[i] = '9';
i--;
}
if (i >= 0)
s[i]--;
// Remove leading zeros
int pos = 0;
while (pos < s.size() - 1 && s[pos] == '0')
pos++;
return s.substr(pos);
}
// Compare two numeric strings
int compare(string a, string b)
{
if (a.size() != b.size())
return a.size() < b.size() ? -1 : 1;
if (a == b)
return 0;
return a < b ? -1 : 1;
}
// Find absolute difference of two numeric strings
string difference(string a, string b)
{
if (compare(a, b) < 0)
swap(a, b);
int i = a.size() - 1;
int j = b.size() - 1;
int borrow = 0;
string res = "";
while (i >= 0)
{
int x = (a[i] - '0') - borrow;
int y = (j >= 0 ? b[j] - '0' : 0);
if (x < y)
{
x += 10;
borrow = 1;
}
else
{
borrow = 0;
}
res += char('0' + (x - y));
i--;
j--;
}
while (res.size() > 1 && res.back() == '0')
res.pop_back();
reverse(res.begin(), res.end());
return res;
}
string closestPalindrome(string &n)
{
// If n itself is a palindrome, return it
if (isPalindrome(n))
return n;
string smaller = subtractOne(n);
string larger = addOne(n);
// Find the closest palindrome smaller than n
while (!isPalindrome(smaller))
smaller = subtractOne(smaller);
// Find the closest palindrome greater than n
while (!isPalindrome(larger))
larger = addOne(larger);
string diff1 = difference(n, smaller);
string diff2 = difference(n, larger);
// Choose the closer palindrome.
// If the difference is equal, choose the smaller one.
if (compare(diff1, diff2) <= 0)
return smaller;
return larger;
}
int main()
{
string n = "9";
cout << closestPalindrome(n) << endl;
return 0;
}
import java.util.*;
class GFG {
// Check whether a number is a palindrome
static boolean isPalindrome(String s)
{
int i = 0, j = s.length() - 1;
while (i < j) {
if (s.charAt(i) != s.charAt(j))
return false;
i++;
j--;
}
return true;
}
// Add 1 to a numeric string
static String addOne(String s)
{
StringBuilder sb = new StringBuilder(s);
int i = sb.length() - 1;
while (i >= 0 && sb.charAt(i) == '9') {
sb.setCharAt(i, '0');
i--;
}
if (i < 0)
return "1" + sb.toString();
sb.setCharAt(i, (char)(sb.charAt(i) + 1));
return sb.toString();
}
// Subtract 1 from a numeric string
static String subtractOne(String s)
{
StringBuilder sb = new StringBuilder(s);
int i = sb.length() - 1;
while (i >= 0 && sb.charAt(i) == '0') {
sb.setCharAt(i, '9');
i--;
}
if (i >= 0)
sb.setCharAt(i, (char)(sb.charAt(i) - 1));
// Remove leading zeros
int pos = 0;
while (pos < sb.length() - 1
&& sb.charAt(pos) == '0')
pos++;
return sb.substring(pos);
}
// Compare two numeric strings
static int compare(String a, String b)
{
if (a.length() != b.length())
return a.length() < b.length() ? -1 : 1;
if (a.equals(b))
return 0;
return a.compareTo(b) < 0 ? -1 : 1;
}
// Find absolute difference of two numeric strings
static String difference(String a, String b)
{
if (compare(a, b) < 0) {
String temp = a;
a = b;
b = temp;
}
int i = a.length() - 1;
int j = b.length() - 1;
int borrow = 0;
StringBuilder res = new StringBuilder();
while (i >= 0) {
int x = (a.charAt(i) - '0') - borrow;
int y = (j >= 0 ? b.charAt(j) - '0' : 0);
if (x < y) {
x += 10;
borrow = 1;
}
else {
borrow = 0;
}
res.append((char)('0' + (x - y)));
i--;
j--;
}
while (res.length() > 1
&& res.charAt(res.length() - 1) == '0')
res.deleteCharAt(res.length() - 1);
return res.reverse().toString();
}
static String closestPalindrome(String n)
{
// If n itself is a palindrome, return it
if (isPalindrome(n))
return n;
String smaller = subtractOne(n);
String larger = addOne(n);
// Find the closest palindrome smaller than n
while (!isPalindrome(smaller))
smaller = subtractOne(smaller);
// Find the closest palindrome greater than n
while (!isPalindrome(larger))
larger = addOne(larger);
String diff1 = difference(n, smaller);
String diff2 = difference(n, larger);
// Choose the closer palindrome.
// If the difference is equal, choose the smaller
// one.
if (compare(diff1, diff2) <= 0)
return smaller;
return larger;
}
public static void main(String[] args)
{
String n = "9";
System.out.println(closestPalindrome(n));
}
}
# Check whether a number is a palindrome
def isPalindrome(s):
i = 0
j = len(s) - 1
while i < j:
if s[i] != s[j]:
return False
i += 1
j -= 1
return True
# Add 1 to a numeric string
def addOne(s):
s = list(s)
i = len(s) - 1
while i >= 0 and s[i] == '9':
s[i] = '0'
i -= 1
if i < 0:
return "1" + ''.join(s)
s[i] = chr(ord(s[i]) + 1)
return ''.join(s)
# Subtract 1 from a numeric string
def subtractOne(s):
s = list(s)
i = len(s) - 1
while i >= 0 and s[i] == '0':
s[i] = '9'
i -= 1
if i >= 0:
s[i] = chr(ord(s[i]) - 1)
# Remove leading zeros
pos = 0
while pos < len(s) - 1 and s[pos] == '0':
pos += 1
return ''.join(s[pos:])
# Compare two numeric strings
def compare(a, b):
if len(a) != len(b):
return -1 if len(a) < len(b) else 1
if a == b:
return 0
return -1 if a < b else 1
# Find absolute difference of two numeric strings
def difference(a, b):
if compare(a, b) < 0:
a, b = b, a
i = len(a) - 1
j = len(b) - 1
borrow = 0
res = []
while i >= 0:
x = (ord(a[i]) - ord('0')) - borrow
y = ord(b[j]) - ord('0') if j >= 0 else 0
if x < y:
x += 10
borrow = 1
else:
borrow = 0
res.append(chr(ord('0') + x - y))
i -= 1
j -= 1
while len(res) > 1 and res[-1] == '0':
res.pop()
return ''.join(reversed(res))
def closestPalindrome(n):
# If n itself is a palindrome, return it
if isPalindrome(n):
return n
smaller = subtractOne(n)
larger = addOne(n)
# Find the closest palindrome smaller than n
while not isPalindrome(smaller):
smaller = subtractOne(smaller)
# Find the closest palindrome greater than n
while not isPalindrome(larger):
larger = addOne(larger)
diff1 = difference(n, smaller)
diff2 = difference(n, larger)
# Choose the closer palindrome.
# If the difference is equal, choose the smaller one.
if compare(diff1, diff2) <= 0:
return smaller
return larger
# Driver Code
if __name__ == "__main__":
n = "9"
print(closestPalindrome(n))
using System;
class GFG {
// Check whether a number is a palindrome
static bool IsPalindrome(string s)
{
int i = 0, j = s.Length - 1;
while (i < j) {
if (s[i] != s[j])
return false;
i++;
j--;
}
return true;
}
// Add 1 to a numeric string
static string AddOne(string s)
{
char[] arr = s.ToCharArray();
int i = arr.Length - 1;
while (i >= 0 && arr[i] == '9') {
arr[i] = '0';
i--;
}
if (i < 0)
return "1" + new string(arr);
arr[i]++;
return new string(arr);
}
// Subtract 1 from a numeric string
static string SubtractOne(string s)
{
char[] arr = s.ToCharArray();
int i = arr.Length - 1;
while (i >= 0 && arr[i] == '0') {
arr[i] = '9';
i--;
}
if (i >= 0)
arr[i]--;
// Remove leading zeros
int pos = 0;
while (pos < arr.Length - 1 && arr[pos] == '0')
pos++;
return new string(arr, pos, arr.Length - pos);
}
// Compare two numeric strings
static int Compare(string a, string b)
{
if (a.Length != b.Length)
return a.Length < b.Length ? -1 : 1;
if (a == b)
return 0;
return string.Compare(a, b,
StringComparison.Ordinal)
< 0
? -1
: 1;
}
// Find absolute difference of two numeric strings
static string Difference(string a, string b)
{
if (Compare(a, b) < 0) {
string temp = a;
a = b;
b = temp;
}
int i = a.Length - 1;
int j = b.Length - 1;
int borrow = 0;
string res = "";
while (i >= 0) {
int x = (a[i] - '0') - borrow;
int y = j >= 0 ? b[j] - '0' : 0;
if (x < y) {
x += 10;
borrow = 1;
}
else {
borrow = 0;
}
res += (char)('0' + (x - y));
i--;
j--;
}
while (res.Length > 1 && res[res.Length - 1] == '0')
res = res.Substring(0, res.Length - 1);
char[] arr = res.ToCharArray();
Array.Reverse(arr);
return new string(arr);
}
static string closestPalindrome(string n)
{
// If n itself is a palindrome, return it
if (IsPalindrome(n))
return n;
string smaller = SubtractOne(n);
string larger = AddOne(n);
// Find the closest palindrome smaller than n
while (!IsPalindrome(smaller))
smaller = SubtractOne(smaller);
// Find the closest palindrome greater than n
while (!IsPalindrome(larger))
larger = AddOne(larger);
string diff1 = Difference(n, smaller);
string diff2 = Difference(n, larger);
// Choose the closer palindrome.
// If the difference is equal, choose the smaller
// one.
if (Compare(diff1, diff2) <= 0)
return smaller;
return larger;
}
public static void Main()
{
string n = "9";
Console.WriteLine(closestPalindrome(n));
}
}
// Check whether a number is a palindrome
function isPalindrome(s)
{
let i = 0;
let j = s.length - 1;
while (i < j) {
if (s[i] !== s[j])
return false;
i++;
j--;
}
return true;
}
// Add 1 to a numeric string
function addOne(s)
{
let arr = s.split("");
let i = arr.length - 1;
while (i >= 0 && arr[i] === "9") {
arr[i] = "0";
i--;
}
if (i < 0)
return "1" + arr.join("");
arr[i] = String.fromCharCode(arr[i].charCodeAt(0) + 1);
return arr.join("");
}
// Subtract 1 from a numeric string
function subtractOne(s)
{
let arr = s.split("");
let i = arr.length - 1;
while (i >= 0 && arr[i] === "0") {
arr[i] = "9";
i--;
}
if (i >= 0)
arr[i]
= String.fromCharCode(arr[i].charCodeAt(0) - 1);
// Remove leading zeros
let pos = 0;
while (pos < arr.length - 1 && arr[pos] === "0")
pos++;
return arr.slice(pos).join("");
}
// Compare two numeric strings
function compare(a, b)
{
if (a.length !== b.length)
return a.length < b.length ? -1 : 1;
if (a === b)
return 0;
return a < b ? -1 : 1;
}
// Find absolute difference of two numeric strings
function difference(a, b)
{
if (compare(a, b) < 0) {
let temp = a;
a = b;
b = temp;
}
let i = a.length - 1;
let j = b.length - 1;
let borrow = 0;
let res = [];
while (i >= 0) {
let x = (a.charCodeAt(i) - 48) - borrow;
let y = j >= 0 ? b.charCodeAt(j) - 48 : 0;
if (x < y) {
x += 10;
borrow = 1;
}
else {
borrow = 0;
}
res.push(String.fromCharCode(48 + x - y));
i--;
j--;
}
while (res.length > 1 && res[res.length - 1] === "0")
res.pop();
return res.reverse().join("");
}
function closestPalindrome(n)
{
// If n itself is a palindrome, return it
if (isPalindrome(n))
return n;
let smaller = subtractOne(n);
let larger = addOne(n);
// Find the closest palindrome smaller than n
while (!isPalindrome(smaller))
smaller = subtractOne(smaller);
// Find the closest palindrome greater than n
while (!isPalindrome(larger))
larger = addOne(larger);
let diff1 = difference(n, smaller);
let diff2 = difference(n, larger);
// Choose the closer palindrome.
// If the difference is equal, choose the smaller one.
if (compare(diff1, diff2) <= 0)
return smaller;
return larger;
}
// Driver Code
let n = "9";
console.log(closestPalindrome(n));
Output
9
Time Complexity: O(k * d), k be the distance from n to the nearest palindrome and d be the number of digits.
Auxiliary Space: O(d)
[Expected Approach] Mirror and Adjust the First Half
The idea is to construct the closest palindrome directly instead of checking every number around n.
A palindrome is determined by its first half, so we take the first half of n and create three candidates by using the same half, one smaller half, and one larger half.
We then compare these candidates with n and choose the closest one, using the smaller palindrome to break ties.
- Take the first half of n.
- Construct a palindrome using the same half.
- Decrease the half by 1 and construct the smaller palindrome.
- Increase the half by 1 and construct the larger palindrome.
- Handle boundary cases such as 1000 → 999 and 999 → 1001.
- Compare all candidates and return the one with minimum difference; if tied, return the smaller palindrome.
#include <bits/stdc++.h>
using namespace std;
// Create a palindrome using the first half
string makePalindrome(string half, int length)
{
string temp = half;
reverse(temp.begin(), temp.end());
if (length % 2 == 0)
return half + temp;
// For odd length, do not duplicate the middle digit
half.pop_back();
return half + temp;
}
// Remove leading zeros
string trimLeadingZeros(string s)
{
int i = 0;
while (i < s.size() - 1 && s[i] == '0')
i++;
return s.substr(i);
}
// Add 1 to a numeric string
string addOne(string s)
{
int i = s.size() - 1;
int carry = 1;
while (i >= 0 && carry)
{
int digit = (s[i] - '0') + carry;
s[i] = char('0' + digit % 10);
carry = digit / 10;
i--;
}
if (carry)
s = "1" + s;
return s;
}
// Subtract 1 from a numeric string
string subtractOne(string s)
{
int i = s.size() - 1;
while (i >= 0 && s[i] == '0')
{
s[i] = '9';
i--;
}
if (i >= 0)
s[i]--;
return trimLeadingZeros(s);
}
// Compare two numeric strings
int compare(string a, string b)
{
a = trimLeadingZeros(a);
b = trimLeadingZeros(b);
if (a.size() != b.size())
return a.size() < b.size() ? -1 : 1;
if (a == b)
return 0;
return a < b ? -1 : 1;
}
// Find absolute difference of two numeric strings
string difference(string a, string b)
{
if (compare(a, b) < 0)
swap(a, b);
int i = a.size() - 1;
int j = b.size() - 1;
int borrow = 0;
string res = "";
while (i >= 0)
{
int x = (a[i] - '0') - borrow;
int y = (j >= 0 ? b[j] - '0' : 0);
if (x < y)
{
x += 10;
borrow = 1;
}
else
{
borrow = 0;
}
res += char('0' + (x - y));
i--;
j--;
}
while (res.size() > 1 && res.back() == '0')
res.pop_back();
reverse(res.begin(), res.end());
return res;
}
string closestPalindrome(string &n)
{
// If n itself is a palindrome, return it
string rev = n;
reverse(rev.begin(), rev.end());
if (n == rev)
return n;
int length = n.size();
// Take the first half of n
string half = n.substr(0, (length + 1) / 2);
// Candidate 1: Use the same half
string same = makePalindrome(half, length);
// Candidate 2: Use a smaller half
string smallerHalf = subtractOne(half);
string smaller;
// Handle the case where the half loses a digit
if (smallerHalf.size() < half.size())
smaller = string(length - 1, '9');
else
smaller = makePalindrome(smallerHalf, length);
// Candidate 3: Use a larger half
string largerHalf = addOne(half);
string larger;
// Handle the case where the half gains a digit
if (largerHalf.size() > half.size())
larger = "1" + string(length - 1, '0') + "1";
else
larger = makePalindrome(largerHalf, length);
// Find the differences from n
string diffSame = difference(n, same);
string diffSmaller = difference(n, smaller);
string diffLarger = difference(n, larger);
// Start with the smaller candidate
string ans = smaller;
string bestDiff = diffSmaller;
// Check the same-half candidate
if (compare(diffSame, bestDiff) < 0 || (compare(diffSame, bestDiff) == 0 && compare(same, ans) < 0))
{
ans = same;
bestDiff = diffSame;
}
// Check the larger candidate
if (compare(diffLarger, bestDiff) < 0 || (compare(diffLarger, bestDiff) == 0 && compare(larger, ans) < 0))
{
ans = larger;
}
return trimLeadingZeros(ans);
}
int main()
{
string n = "9";
cout << closestPalindrome(n) << endl;
return 0;
}
class GFG {
// Create a palindrome using the first half
static String makePalindrome(String half, int length)
{
String temp
= new StringBuilder(half).reverse().toString();
if (length % 2 == 0)
return half + temp;
// For odd length, do not duplicate the middle digit
half = half.substring(0, half.length() - 1);
return half + temp;
}
// Remove leading zeros
static String trimLeadingZeros(String s)
{
int i = 0;
while (i < s.length() - 1 && s.charAt(i) == '0')
i++;
return s.substring(i);
}
// Add 1 to a numeric string
static String addOne(String s)
{
StringBuilder sb = new StringBuilder(s);
int i = sb.length() - 1;
int carry = 1;
while (i >= 0 && carry > 0) {
int digit = (sb.charAt(i) - '0') + carry;
sb.setCharAt(i, (char)('0' + digit % 10));
carry = digit / 10;
i--;
}
if (carry > 0)
sb.insert(0, '1');
return sb.toString();
}
// Subtract 1 from a numeric string
static String subtractOne(String s)
{
StringBuilder sb = new StringBuilder(s);
int i = sb.length() - 1;
while (i >= 0 && sb.charAt(i) == '0') {
sb.setCharAt(i, '9');
i--;
}
if (i >= 0)
sb.setCharAt(i, (char)(sb.charAt(i) - 1));
return trimLeadingZeros(sb.toString());
}
// Compare two numeric strings
static int compare(String a, String b)
{
a = trimLeadingZeros(a);
b = trimLeadingZeros(b);
if (a.length() != b.length())
return a.length() < b.length() ? -1 : 1;
if (a.equals(b))
return 0;
return a.compareTo(b) < 0 ? -1 : 1;
}
// Find absolute difference of two numeric strings
static String difference(String a, String b)
{
if (compare(a, b) < 0) {
String temp = a;
a = b;
b = temp;
}
int i = a.length() - 1;
int j = b.length() - 1;
int borrow = 0;
StringBuilder res = new StringBuilder();
while (i >= 0) {
int x = (a.charAt(i) - '0') - borrow;
int y = (j >= 0 ? b.charAt(j) - '0' : 0);
if (x < y) {
x += 10;
borrow = 1;
}
else {
borrow = 0;
}
res.append((char)('0' + (x - y)));
i--;
j--;
}
while (res.length() > 1
&& res.charAt(res.length() - 1) == '0')
res.deleteCharAt(res.length() - 1);
return res.reverse().toString();
}
static String closestPalindrome(String n)
{
// If n itself is a palindrome, return it
String rev
= new StringBuilder(n).reverse().toString();
if (n.equals(rev))
return n;
int length = n.length();
// Take the first half of n
String half = n.substring(0, (length + 1) / 2);
// Candidate 1: Use the same half
String same = makePalindrome(half, length);
// Candidate 2: Use a smaller half
String smallerHalf = subtractOne(half);
String smaller;
// Handle the case where the half loses a digit
if (smallerHalf.length() < half.length())
smaller = "9".repeat(length - 1);
else
smaller = makePalindrome(smallerHalf, length);
// Candidate 3: Use a larger half
String largerHalf = addOne(half);
String larger;
// Handle the case where the half gains a digit
if (largerHalf.length() > half.length())
larger = "1"
+ "0".repeat(length - 1) + "1";
else
larger = makePalindrome(largerHalf, length);
// Find the differences from n
String diffSame = difference(n, same);
String diffSmaller = difference(n, smaller);
String diffLarger = difference(n, larger);
// Start with the smaller candidate
String ans = smaller;
String bestDiff = diffSmaller;
// Check the same-half candidate
if (compare(diffSame, bestDiff) < 0
|| (compare(diffSame, bestDiff) == 0
&& compare(same, ans) < 0)) {
ans = same;
bestDiff = diffSame;
}
// Check the larger candidate
if (compare(diffLarger, bestDiff) < 0
|| (compare(diffLarger, bestDiff) == 0
&& compare(larger, ans) < 0)) {
ans = larger;
}
return trimLeadingZeros(ans);
}
public static void main(String[] args)
{
String n = "9";
System.out.println(closestPalindrome(n));
}
}
# Create a palindrome using the first half
def makePalindrome(half, length):
temp = half[::-1]
if length % 2 == 0:
return half + temp
# For odd length, do not duplicate the middle digit
half = half[:-1]
return half + temp
# Remove leading zeros
def trimLeadingZeros(s):
i = 0
while i < len(s) - 1 and s[i] == '0':
i += 1
return s[i:]
# Add 1 to a numeric string
def addOne(s):
s = list(s)
i = len(s) - 1
carry = 1
while i >= 0 and carry:
digit = (ord(s[i]) - ord('0')) + carry
s[i] = chr(ord('0') + digit % 10)
carry = digit // 10
i -= 1
if carry:
s.insert(0, '1')
return ''.join(s)
# Subtract 1 from a numeric string
def subtractOne(s):
s = list(s)
i = len(s) - 1
while i >= 0 and s[i] == '0':
s[i] = '9'
i -= 1
if i >= 0:
s[i] = chr(ord(s[i]) - 1)
return trimLeadingZeros(''.join(s))
# Compare two numeric strings
def compare(a, b):
a = trimLeadingZeros(a)
b = trimLeadingZeros(b)
if len(a) != len(b):
return -1 if len(a) < len(b) else 1
if a == b:
return 0
return -1 if a < b else 1
# Find absolute difference of two numeric strings
def difference(a, b):
if compare(a, b) < 0:
a, b = b, a
i = len(a) - 1
j = len(b) - 1
borrow = 0
res = []
while i >= 0:
x = (ord(a[i]) - ord('0')) - borrow
y = ord(b[j]) - ord('0') if j >= 0 else 0
if x < y:
x += 10
borrow = 1
else:
borrow = 0
res.append(chr(ord('0') + x - y))
i -= 1
j -= 1
while len(res) > 1 and res[-1] == '0':
res.pop()
return ''.join(reversed(res))
def closestPalindrome(n):
# If n itself is a palindrome, return it
if n == n[::-1]:
return n
length = len(n)
# Take the first half of n
half = n[:(length + 1) // 2]
# Candidate 1: Use the same half
same = makePalindrome(half, length)
# Candidate 2: Use a smaller half
smallerHalf = subtractOne(half)
# Handle the case where the half loses a digit
if len(smallerHalf) < len(half):
smaller = '9' * (length - 1)
else:
smaller = makePalindrome(smallerHalf, length)
# Candidate 3: Use a larger half
largerHalf = addOne(half)
# Handle the case where the half gains a digit
if len(largerHalf) > len(half):
larger = '1' + '0' * (length - 1) + '1'
else:
larger = makePalindrome(largerHalf, length)
# Find the differences from n
diffSame = difference(n, same)
diffSmaller = difference(n, smaller)
diffLarger = difference(n, larger)
# Start with the smaller candidate
ans = smaller
bestDiff = diffSmaller
# Check the same-half candidate
if compare(diffSame, bestDiff) < 0 or \
(compare(diffSame, bestDiff) == 0 and
compare(same, ans) < 0):
ans = same
bestDiff = diffSame
# Check the larger candidate
if compare(diffLarger, bestDiff) < 0 or \
(compare(diffLarger, bestDiff) == 0 and
compare(larger, ans) < 0):
ans = larger
return trimLeadingZeros(ans)
# Driver Code
if __name__ == "__main__":
n = "9"
print(closestPalindrome(n))
using System;
class GFG {
// Create a palindrome using the first half
static string MakePalindrome(string half, int length)
{
char[] tempArr = half.ToCharArray();
Array.Reverse(tempArr);
string temp = new string(tempArr);
if (length % 2 == 0)
return half + temp;
// For odd length, do not duplicate the middle digit
half = half.Substring(0, half.Length - 1);
return half + temp;
}
// Remove leading zeros
static string TrimLeadingZeros(string s)
{
int i = 0;
while (i < s.Length - 1 && s[i] == '0')
i++;
return s.Substring(i);
}
// Add 1 to a numeric string
static string AddOne(string s)
{
char[] arr = s.ToCharArray();
int i = arr.Length - 1;
int carry = 1;
while (i >= 0 && carry > 0) {
int digit = (arr[i] - '0') + carry;
arr[i] = (char)('0' + digit % 10);
carry = digit / 10;
i--;
}
if (carry > 0)
return "1" + new string(arr);
return new string(arr);
}
// Subtract 1 from a numeric string
static string SubtractOne(string s)
{
char[] arr = s.ToCharArray();
int i = arr.Length - 1;
while (i >= 0 && arr[i] == '0') {
arr[i] = '9';
i--;
}
if (i >= 0)
arr[i]--;
return TrimLeadingZeros(new string(arr));
}
// Compare two numeric strings
static int Compare(string a, string b)
{
a = TrimLeadingZeros(a);
b = TrimLeadingZeros(b);
if (a.Length != b.Length)
return a.Length < b.Length ? -1 : 1;
if (a == b)
return 0;
return string.Compare(a, b,
StringComparison.Ordinal)
< 0
? -1
: 1;
}
// Find absolute difference of two numeric strings
static string Difference(string a, string b)
{
if (Compare(a, b) < 0) {
string temp = a;
a = b;
b = temp;
}
int i = a.Length - 1;
int j = b.Length - 1;
int borrow = 0;
string res = "";
while (i >= 0) {
int x = (a[i] - '0') - borrow;
int y = j >= 0 ? b[j] - '0' : 0;
if (x < y) {
x += 10;
borrow = 1;
}
else {
borrow = 0;
}
res += (char)('0' + x - y);
i--;
j--;
}
while (res.Length > 1
&& res[res.Length - 1] == '0') {
res = res.Substring(0, res.Length - 1);
}
char[] arr = res.ToCharArray();
Array.Reverse(arr);
return new string(arr);
}
static string closestPalindrome(string n)
{
// If n itself is a palindrome, return it
char[] revArr = n.ToCharArray();
Array.Reverse(revArr);
if (n == new string(revArr))
return n;
int length = n.Length;
// Take the first half of n
string half = n.Substring(0, (length + 1) / 2);
// Candidate 1: Use the same half
string same = MakePalindrome(half, length);
// Candidate 2: Use a smaller half
string smallerHalf = SubtractOne(half);
string smaller;
// Handle the case where the half loses a digit
if (smallerHalf.Length < half.Length)
smaller = new string('9', length - 1);
else
smaller = MakePalindrome(smallerHalf, length);
// Candidate 3: Use a larger half
string largerHalf = AddOne(half);
string larger;
// Handle the case where the half gains a digit
if (largerHalf.Length > half.Length)
larger
= "1" + new string('0', length - 1) + "1";
else
larger = MakePalindrome(largerHalf, length);
// Find the differences from n
string diffSame = Difference(n, same);
string diffSmaller = Difference(n, smaller);
string diffLarger = Difference(n, larger);
// Start with the smaller candidate
string ans = smaller;
string bestDiff = diffSmaller;
// Check the same-half candidate
if (Compare(diffSame, bestDiff) < 0
|| (Compare(diffSame, bestDiff) == 0
&& Compare(same, ans) < 0)) {
ans = same;
bestDiff = diffSame;
}
// Check the larger candidate
if (Compare(diffLarger, bestDiff) < 0
|| (Compare(diffLarger, bestDiff) == 0
&& Compare(larger, ans) < 0)) {
ans = larger;
}
return TrimLeadingZeros(ans);
}
public static void Main()
{
string n = "9";
Console.WriteLine(closestPalindrome(n));
}
}
// Create a palindrome using the first half
function makePalindrome(half, length)
{
let temp = half.split("").reverse().join("");
if (length % 2 === 0)
return half + temp;
// For odd length, do not duplicate the middle digit
half = half.slice(0, -1);
return half + temp;
}
// Remove leading zeros
function trimLeadingZeros(s)
{
let i = 0;
while (i < s.length - 1 && s[i] === "0")
i++;
return s.slice(i);
}
// Add 1 to a numeric string
function addOne(s)
{
let arr = s.split("");
let i = arr.length - 1;
let carry = 1;
while (i >= 0 && carry) {
let digit = (arr[i].charCodeAt(0) - 48) + carry;
arr[i] = String.fromCharCode(48 + digit % 10);
carry = Math.floor(digit / 10);
i--;
}
if (carry)
arr.unshift("1");
return arr.join("");
}
// Subtract 1 from a numeric string
function subtractOne(s)
{
let arr = s.split("");
let i = arr.length - 1;
while (i >= 0 && arr[i] === "0") {
arr[i] = "9";
i--;
}
if (i >= 0)
arr[i]
= String.fromCharCode(arr[i].charCodeAt(0) - 1);
return trimLeadingZeros(arr.join(""));
}
// Compare two numeric strings
function compare(a, b)
{
a = trimLeadingZeros(a);
b = trimLeadingZeros(b);
if (a.length !== b.length)
return a.length < b.length ? -1 : 1;
if (a === b)
return 0;
return a < b ? -1 : 1;
}
// Find absolute difference of two numeric strings
function difference(a, b)
{
if (compare(a, b) < 0) {
let temp = a;
a = b;
b = temp;
}
let i = a.length - 1;
let j = b.length - 1;
let borrow = 0;
let res = [];
while (i >= 0) {
let x = (a.charCodeAt(i) - 48) - borrow;
let y = j >= 0 ? b.charCodeAt(j) - 48 : 0;
if (x < y) {
x += 10;
borrow = 1;
}
else {
borrow = 0;
}
res.push(String.fromCharCode(48 + x - y));
i--;
j--;
}
while (res.length > 1 && res[res.length - 1] === "0")
res.pop();
return res.reverse().join("");
}
function closestPalindrome(n)
{
// If n itself is a palindrome, return it
let rev = n.split("").reverse().join("");
if (n === rev)
return n;
let length = n.length;
// Take the first half of n
let half = n.slice(0, Math.floor((length + 1) / 2));
// Candidate 1: Use the same half
let same = makePalindrome(half, length);
// Candidate 2: Use a smaller half
let smallerHalf = subtractOne(half);
let smaller;
// Handle the case where the half loses a digit
if (smallerHalf.length < half.length)
smaller = "9".repeat(length - 1);
else
smaller = makePalindrome(smallerHalf, length);
// Candidate 3: Use a larger half
let largerHalf = addOne(half);
let larger;
// Handle the case where the half gains a digit
if (largerHalf.length > half.length)
larger = "1" +
"0".repeat(length - 1) + "1";
else
larger = makePalindrome(largerHalf, length);
// Find the differences from n
let diffSame = difference(n, same);
let diffSmaller = difference(n, smaller);
let diffLarger = difference(n, larger);
// Start with the smaller candidate
let ans = smaller;
let bestDiff = diffSmaller;
// Check the same-half candidate
if (compare(diffSame, bestDiff) < 0
|| (compare(diffSame, bestDiff) === 0
&& compare(same, ans) < 0)) {
ans = same;
bestDiff = diffSame;
}
// Check the larger candidate
if (compare(diffLarger, bestDiff) < 0
|| (compare(diffLarger, bestDiff) === 0
&& compare(larger, ans) < 0)) {
ans = larger;
}
return trimLeadingZeros(ans);
}
// Driver Code
let n = "9";
console.log(closestPalindrome(n));
Output
9
Time Complexity: O(d), d is the number of digits in n.
Auxiliary Space: O(d)