Make Largest Palindrome by Changing at Most K-Digits

Last Updated : 3 Oct, 2026

Given a string s consisting of digits (0-9) and an integer k. Convert the string into a palindrome by changing at most k digits. If multiple palindromes are possible, return the lexicographically largest one. If it's impossible to form a palindrome with k changes, return "-1".

Examples: 

Input: s = "19495", k = 3
Output: "99999"
Explanation: Change 1 and 5 to 9, and then change the middle digit 4 to 9, using exactly 3 changes to form the lexicographically largest palindrome "99999".

Input: s = "11345", k = 1
Output: "-1"
Explanation: It is not possible to make s palindrome after 1 changes.

Try It Yourself
redirect icon

[Naive Approach] Recursion - O(10 ^ n * n) Time and O(n) Space

The idea is to try all possible digits at each position and generate every string that can be formed using at most k changes. Among the generated strings, keep the lexicographically largest palindrome.

Working of Approach:

  • Recursively keep the current digit or change it to another digit.
  • For every generated string, check if it is a palindrome.
  • Update the answer whenever a larger palindrome is found.
C++
#include <iostream>
#include <string>
using namespace std;

string res;

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;
}

void generate(string &s, int pos, int k)
{
    int n = s.length();

    // Check the generated string.
    if (pos == n)
    {
        if (isPalindrome(s) && s > res)
            res = s;

        return;
    }

    // Keep the current digit.
    generate(s, pos + 1, k);

    char original = s[pos];

    // Try changing the digit.
    for (char digit = '0'; digit <= '9'; digit++)
    {
        if (digit == original || k == 0)
            continue;

        s[pos] = digit;
        generate(s, pos + 1, k - 1);
    }

    s[pos] = original;
}

string maxPalindrome(string &s, int k)
{
    res = "";

    generate(s, 0, k);

    if (res == "")
        return "-1";

    return res;
}

int main()
{
    string s = "19495";
    int k = 3;

    cout << "\"" << maxPalindrome(s, k) << "\"" << endl;

    return 0;
}
Java
import java.util.*;

public class GFG {
    static String res;

    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;
    }

    static void generate(char[] s, int pos, int k)
    {
        int n = s.length;

        // Check the generated string.
        if (pos == n) {
            if (isPalindrome(new String(s))
                && new String(s).compareTo(res) > 0)
                res = new String(s);

            return;
        }

        // Keep the current digit.
        generate(s, pos + 1, k);

        char original = s[pos];

        // Try changing the digit.
        for (char digit = '0'; digit <= '9'; digit++) {
            if (digit == original || k == 0)
                continue;

            s[pos] = digit;
            generate(s, pos + 1, k - 1);
        }

        s[pos] = original;
    }

    static String maxPalindrome(String s, int k)
    {
        res = "";

        generate(s.toCharArray(), 0, k);

        if (res.equals(""))
            return "-1";

        return res;
    }

    public static void main(String[] args)
    {
        String s = "19495";
        int k = 3;

        System.out.println("\"" + maxPalindrome(s, k)
                           + "\"");
    }
}
Python
res = ""


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


def generate(s, pos, k):
    global res

    n = len(s)

    # Check the generated string.
    if pos == n:
        if isPalindrome(s) and s > res:
            res = s

        return

    # Keep the current digit.
    generate(s, pos + 1, k)

    original = s[pos]

    # Try changing the digit.
    for digit in range(48, 58):

        # Skip the original digit or if no changes are left.
        if chr(digit) == original or k == 0:
            continue

        s = s[:pos] + chr(digit) + s[pos + 1:]

        # Generate using one change.
        generate(s, pos + 1, k - 1)

        # Restore the original digit.
        s = s[:pos] + original + s[pos + 1:]


def maxPalindrome(s, k):
    global res
    res = ""

    generate(s, 0, k)

    if res == "":
        return "-1"

    return res


if __name__ == '__main__':
    s = "19495"
    k = 3

    print(maxPalindrome(s, k))
C#
using System;

public class GFG {
    static string res;

    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;
    }

    static void Generate(char[] s, int pos, int k)
    {
        int n = s.Length;

        // Check the generated string.
        if (pos == n) {
            if (IsPalindrome(new string(s))
                && string.Compare(new string(s), res) > 0)
                res = new string(s);

            return;
        }

        // Keep the current digit.
        Generate(s, pos + 1, k);

        char original = s[pos];

        // Try changing the digit.
        for (char digit = '0'; digit <= '9'; digit++) {
            if (digit == original || k == 0)
                continue;

            s[pos] = digit;
            Generate(s, pos + 1, k - 1);
        }

        s[pos] = original;
    }

    static string maxPalindrome(string s, int k)
    {
        res = "";

        Generate(s.ToCharArray(), 0, k);

        if (res == "")
            return "-1";

        return res;
    }

    public static void Main()
    {
        string s = "19495";
        int k = 3;

        Console.WriteLine("\"" + maxPalindrome(s, k)
                          + "\"");
    }
}
JavaScript
function isPalindrome(s) {
    let i = 0, j = s.length - 1;

    while (i < j) {
        if (s[i] !== s[j])
            return false;

        i++;
        j--;
    }

    return true;
}

function generate(s, pos, k, resObj) {
    let n = s.length;

    // Check the generated string.
    if (pos === n) {
        let currentStr = s.join('');
        if (isPalindrome(s) && currentStr > resObj.val)
            resObj.val = currentStr;

        return;
    }

    // Keep the current digit.
    generate(s, pos + 1, k, resObj);

    let original = s[pos];

    // Try changing the digit.
    for (let d = 0; d <= 9; d++) {
        let digit = String(d);
        if (digit === original || k === 0)
            continue;

        s[pos] = digit;
        generate(s, pos + 1, k - 1, resObj);
    }

    s[pos] = original;
}

function maxPalindrome(sStr, k) {
    let resObj = { val: "" };
    let s = sStr.split('');
    
    generate(s, 0, k, resObj);

    if (resObj.val === "")
        return "-1";

    return resObj.val;
}

// Driver code
let s = "19495";
let k = 3;

console.log("\"" + maxPalindrome(s, k) + "\"");

Output
"99999"

[Better Approach] Two Pointers - O(n) time and O(n) space

The idea is to use two pointers from both ends to first make the string a palindrome. We store which pairs were changed, then use the remaining changes to make the palindrome lexicographically largest.

  • Replace the smaller digit with the larger one and mark the pair as changed.
  • Traverse again and change pairs to '9' using the remaining changes.
  • If one change remains for an odd-length string, make the middle digit '9'.

Let us understand with an example:
Input: s = "19495", k = 3

  • Compare 1 and 5 -> different, change 1 to 5, mark the pair, k = 2 -> "59495".
  • Compare 9 and 9 -> same, no change -> "59495".
  • Compare 4 with itself -> no change needed.
  • Traverse again: change the marked pair 5 and 5 to 9, k = 1 -> "99499".
  • Change the middle 4 to 9 -> "99999".
C++
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
using namespace std;

string maxPalindrome(string &s, int k)
{
    int n = s.length();
    vector<bool> changed(n, false);

    // Make the string a palindrome.
    int i = 0, j = n - 1;

    while (i < j)
    {
        if (s[i] != s[j])
        {
            // Replace the smaller digit with the larger digit.
            if (s[i] < s[j])
                s[i] = s[j];
            else
                s[j] = s[i];

            // Mark this pair as changed.
            changed[i] = changed[j] = true;
            k--;
        }

        i++;
        j--;
    }

    // Return -1 if it is not possible to make a palindrome.
    if (k < 0)
        return "-1";

    // Maximize the palindrome using the remaining changes.
    i = 0;
    j = n - 1;

    while (i < j)
    {
        if (s[i] != '9')
        {
            // One extra change is enough for an already changed pair.
            if (changed[i] && k >= 1)
            {
                s[i] = s[j] = '9';
                k--;
            }

            // Two changes are needed for an unchanged pair.
            else if (!changed[i] && k >= 2)
            {
                s[i] = s[j] = '9';
                k -= 2;
            }
        }

        i++;
        j--;
    }

    // Make the middle digit 9 if one change is available.
    if (i == j && k > 0)
        s[i] = '9';

    // Return the largest possible palindrome.
    return s;
}

int main()
{
    string s = "19495";
    int k = 3;

    cout << "\"" << maxPalindrome(s, k) << "\"" << endl;

    return 0;
}
Java
import java.util.Arrays;

public class GFG {
    public static String maxPalindrome(String s, int k)
    {
        int n = s.length();
        boolean[] changed = new boolean[n];
        Arrays.fill(changed, false);

        // Make the string a palindrome.
        int i = 0, j = n - 1;

        while (i < j) {
            if (s.charAt(i) != s.charAt(j)) {
                // Replace the smaller digit with the larger
                // digit.
                if (s.charAt(i) < s.charAt(j))
                    s = s.substring(0, i) + s.charAt(j)
                        + s.substring(i + 1);
                else
                    s = s.substring(0, j) + s.charAt(i)
                        + s.substring(j + 1);

                // Mark this pair as changed.
                changed[i] = changed[j] = true;
                k--;
            }

            i++;
            j--;
        }

        // Return -1 if it is not possible to make a
        // palindrome.
        if (k < 0)
            return "-1";

        // Maximize the palindrome using the remaining
        // changes.
        i = 0;
        j = n - 1;

        while (i < j) {
            if (s.charAt(i) != '9') {
                // One extra change is enough for an already
                // changed pair.
                if (changed[i] && k >= 1) {
                    s = s.substring(0, i) + '9'
                        + s.substring(i + 1);
                    s = s.substring(0, j) + '9'
                        + s.substring(j + 1);
                    k--;
                }

                // Two changes are needed for an unchanged
                // pair.
                else if (!changed[i] && k >= 2) {
                    s = s.substring(0, i) + '9'
                        + s.substring(i + 1);
                    s = s.substring(0, j) + '9'
                        + s.substring(j + 1);
                    k -= 2;
                }
            }

            i++;
            j--;
        }

        // Make the middle digit 9 if one change is
        // available.
        if (i == j && k > 0)
            s = s.substring(0, i) + '9'
                + s.substring(i + 1);

        // Return the largest possible palindrome.
        return s;
    }

    public static void main(String[] args)
    {
        String s = "19495";
        int k = 3;

        System.out.println("\"" + maxPalindrome(s, k)
                           + "\"");
    }
}
Python
def maxPalindrome(s, k):
    n = len(s)
    changed = [False] * n

    # Make the string a palindrome.
    i = 0
    j = n - 1

    while i < j:
        if s[i]!= s[j]:
            # Replace the smaller digit with the larger digit.
            if s[i] < s[j]:
                s = s[:i] + s[j] + s[i+1:]
            else:
                s = s[:j] + s[i] + s[j+1:]

            # Mark this pair as changed.
            changed[i] = changed[j] = True
            k -= 1

        i += 1
        j -= 1

    # Return -1 if it is not possible to make a palindrome.
    if k < 0:
        return "-1"

    # Maximize the palindrome using the remaining changes.
    i = 0
    j = n - 1

    while i < j:
        if s[i]!= '9':
            # One extra change is enough for an already changed pair.
            if changed[i] and k >= 1:
                s = s[:i] + '9' + s[i+1:]
                s = s[:j] + '9' + s[j+1:]
                k -= 1
            # Two changes are needed for an unchanged pair.
            elif not changed[i] and k >= 2:
                s = s[:i] + '9' + s[i+1:]
                s = s[:j] + '9' + s[j+1:]
                k -= 2
        i += 1
        j -= 1

    # Make the middle digit 9 if one change is available.
    if i == j and k > 0:
        s = s[:i] + '9' + s[i+1:]

    # Return the largest possible palindrome.
    return s


if __name__ == '__main__':
    s = "19495"
    k = 3
    print(f'"{maxPalindrome(s, k)}"')
C#
using System;
using System.Collections.Generic;

class GFG {
    static string maxPalindrome(string s, int k)
    {
        int n = s.Length;
        List<bool> changed = new List<bool>(new bool[n]);

        // Make the string a palindrome.
        int i = 0, j = n - 1;

        while (i < j) {
            if (s[i] != s[j]) {
                // Replace the smaller digit with the larger
                // digit.
                if (s[i] < s[j])
                    s = s.Substring(0, i) + s[j]
                        + s.Substring(i + 1);
                else
                    s = s.Substring(0, j) + s[i]
                        + s.Substring(j + 1);

                // Mark this pair as changed.
                changed[i] = changed[j] = true;
                k--;
            }

            i++;
            j--;
        }

        // Return -1 if it is not possible to make a
        // palindrome.
        if (k < 0)
            return "-1";

        // Maximize the palindrome using the remaining
        // changes.
        i = 0;
        j = n - 1;

        while (i < j) {
            if (s[i] != '9') {
                // One extra change is enough for an already
                // changed pair.
                if (changed[i] && k >= 1) {
                    char[] charArray = s.ToCharArray();
                    charArray[i] = charArray[j] = '9';
                    s = new string(charArray);
                    k--;
                }

                // Two changes are needed for an unchanged
                // pair.
                else if (!changed[i] && k >= 2) {
                    char[] charArray = s.ToCharArray();
                    charArray[i] = charArray[j] = '9';
                    s = new string(charArray);
                    k -= 2;
                }
            }

            i++;
            j--;
        }

        // Make the middle digit 9 if one change is
        // available.
        if (i == j && k > 0)
            s = s.Substring(0, i) + '9'
                + s.Substring(i + 1);

        // Return the largest possible palindrome.
        return s;
    }

    static void Main(string[] args)
    {
        string s = "19495";
        int k = 3;

        Console.WriteLine("\"" + maxPalindrome(s, k)
                          + "\"");
    }
}
JavaScript
function maxPalindrome(s, k)
{
    let n = s.length;
    let changed = new Array(n).fill(false);

    // Make the string a palindrome.
    let i = 0, j = n - 1;

    while (i < j) {
        if (s[i] !== s[j]) {
            // Replace the smaller digit with the larger
            // digit.
            if (s[i] < s[j]) {
                s = s.substring(0, i) + s[j]
                    + s.substring(i + 1);
            }
            else {
                s = s.substring(0, j) + s[i]
                    + s.substring(j + 1);
            }

            // Mark this pair as changed.
            changed[i] = changed[j] = true;
            k--;
        }

        i++;
        j--;
    }

    // Return -1 if it is not possible to make a palindrome.
    if (k < 0) {
        return "-1";
    }

    // Maximize the palindrome using the remaining changes.
    i = 0;
    j = n - 1;

    while (i < j) {
        if (s[i] !== "9") {
            // One extra change is enough for an already
            // changed pair.
            if (changed[i] && k >= 1) {
                s = s.substring(0, i) + "9"
                    + s.substring(i + 1);
                s = s.substring(0, j) + "9"
                    + s.substring(j + 1);
                k--;
            }

            // Two changes are needed for an unchanged pair.
            else if (!changed[i] && k >= 2) {
                s = s.substring(0, i) + "9"
                    + s.substring(i + 1);
                s = s.substring(0, j) + "9"
                    + s.substring(j + 1);
                k -= 2;
            }
        }

        i++;
        j--;
    }

    // Make the middle digit 9 if one change is available.
    if (i === j && k > 0) {
        s = s.substring(0, i) + "9" + s.substring(i + 1);
    }

    // Return the largest possible palindrome.
    return s;
}

// Driver Code
let s = "19495";
let k = 3;

console.log(`'${maxPalindrome(s, k)}'`);

Output
"99999"

[Expected Approach] Greedy Algorithm - O(n) time and O(1) space

In this approach, we greedily count the changes needed to make the string a palindrome. Then, use the remaining changes to make the palindrome as large as possible.

  • Compare characters from both ends and count required changes.
  • Traverse again and change the largest possible digits to '9'.
  • If the required changes exceed k, return "-1".

Let us understand with an example:
Input: s = "19495", k = 3

  • Compare 1 and 5 -> different, so replacements = 1.
  • Compare 9 and 9 -> same, no change needed.
  • Change 1 and 5 to 9 using 2 changes -> s = "99499", k = 1.
  • Change the middle digit 4 to 9 -> s = "99999".

Return "99999".

C++
#include <algorithm>
#include <iostream>
#include <string>
using namespace std;

string maxPalindrome(string &s, int k)
{
    int n = s.length();
    int replacements = 0;

    // Count changes needed to make the string a palindrome.
    for (int i = 0, j = n - 1; i < j; i++, j--)
    {
        if (s[i] != s[j])
        {
            replacements++;

            // -1 if required changes exceed k.
            if (replacements > k)
                return "-1";
        }
    }

    // Maximize the palindrome using the remaining changes.
    for (int i = 0, j = n - 1; i <= j && k > 0; i++, j--)
    {

        // Maximize the middle digit for odd length.
        if (i == j)
        {
            s[i] = '9';
        }

        // Handle different mirror digits.
        else if (s[i] != s[j])
        {

            // Use one extra change to make both digits 9.
            if (k - replacements >= 1 && max(s[i], s[j]) != '9')
            {
                s[i] = s[j] = '9';
                replacements--;
                k -= 2;
            }

            // Otherwise, make both digits equal to the larger digit.
            else
            {
                s[i] = s[j] = max(s[i], s[j]);
                replacements--;
                k--;
            }
        }

        // Make an equal pair 9 if two extra changes are available.
        else if (k - replacements >= 2 && s[i] != '9')
        {
            s[i] = s[j] = '9';
            k -= 2;
        }
    }

    // Return the largest possible palindrome.
    return s;
}

int main()
{

    string s = "19495";
    int k = 3;

    cout << "\"" << maxPalindrome(s, k) << "\"" << endl;

    return 0;
}
Java
import java.util.*;

public class GFG {
    public static String maxPalindrome(String s, int k)
    {
        int n = s.length();
        int replacements = 0;

        // Count changes needed to make the string a
        // palindrome.
        for (int i = 0, j = n - 1; i < j; i++, j--) {
            if (s.charAt(i) != s.charAt(j)) {
                replacements++;

                // -1 if required changes exceed k.
                if (replacements > k)
                    return "-1";
            }
        }

        // Maximize the palindrome using the remaining
        // changes.
        char[] charArray = s.toCharArray();
        for (int i = 0, j = n - 1; i <= j && k > 0;
             i++, j--) {

            // Maximize the middle digit for odd length.
            if (i == j) {
                charArray[i] = '9';
            }

            // Handle different mirror digits.
            else if (charArray[i] != charArray[j]) {

                // Use one extra change to make both
                // digits 9.
                if (k - replacements >= 1
                    && Math.max(charArray[i], charArray[j])
                           != '9') {
                    charArray[i] = charArray[j] = '9';
                    replacements--;
                    k -= 2;
                }

                // Otherwise, make both digits equal to the
                // larger digit.
                else {
                    charArray[i] = charArray[j]
                        = (char)Math.max(charArray[i],
                                         charArray[j]);
                    replacements--;
                    k--;
                }
            }

            // Make an equal pair 9 if two extra changes are
            // available.
            else if (k - replacements >= 2
                     && charArray[i] != '9') {
                charArray[i] = charArray[j] = '9';
                k -= 2;
            }
        }
        return new String(charArray);
    }

    public static void main(String[] args)
    {
        String s = "19495";
        int k = 3;

        System.out.println("\"" + maxPalindrome(s, k)
                           + "\"");
    }
}
Python
def maxPalindrome(s, k):
    n = len(s)
    replacements = 0

    # Count changes needed to make the string a palindrome.
    for i in range(n // 2):
        if s[i] != s[n - 1 - i]:
            replacements += 1

            # -1 if required changes exceed k.
            if replacements > k:
                return "-1"

    # Maximize the palindrome using the remaining changes.
    s = list(s)

    for i in range((n + 1) // 2):
        j = n - 1 - i

        if k <= 0:
            break

        # Maximize the middle digit for odd length.
        if i == j:
            s[i] = '9'

        # Handle different mirror digits.
        elif s[i] != s[j]:

            # Use one extra change to make both digits 9.
            if k - replacements >= 1 and max(s[i], s[j]) != '9':
                s[i] = s[j] = '9'
                replacements -= 1
                k -= 2

            # Otherwise, make both digits equal to the larger digit.
            else:
                s[i] = s[j] = max(s[i], s[j])
                replacements -= 1
                k -= 1

        # Make an equal pair 9 if two extra changes are available.
        elif k - replacements >= 2 and s[i] != '9':
            s[i] = s[j] = '9'
            k -= 2

    return ''.join(s)


if __name__ == '__main__':
    s = "19495"
    k = 3

    print(f'"{maxPalindrome(s, k)}"')
C#
using System;

class GFG {
    static string maxPalindrome(string s, int k)
    {
        int n = s.Length;
        int replacements = 0;

        // Count changes needed to make the string a
        // palindrome.
        for (int i = 0, j = n - 1; i < j; i++, j--) {
            if (s[i] != s[j]) {
                replacements++;

                // -1 if required changes exceed k.
                if (replacements > k)
                    return "-1";
            }
        }

        // Maximize the palindrome using the remaining
        // changes.
        char[] charArray = s.ToCharArray();
        for (int i = 0, j = n - 1; i <= j && k > 0;
             i++, j--) {

            // Maximize the middle digit for odd length.
            if (i == j) {
                charArray[i] = '9';
            }

            // Handle different mirror digits.
            else if (charArray[i] != charArray[j]) {

                // Use one extra change to make both
                // digits 9.
                if (k - replacements >= 1
                    && Math.Max(charArray[i], charArray[j])
                           != '9') {
                    charArray[i] = charArray[j] = '9';
                    replacements--;
                    k -= 2;
                }

                // Otherwise, make both digits equal to the
                // larger digit.
                else {
                    charArray[i] = charArray[j]
                        = (char)Math.Max(charArray[i],
                                         charArray[j]);
                    replacements--;
                    k--;
                }
            }

            // Make an equal pair 9 if two extra changes are
            // available.
            else if (k - replacements >= 2
                     && charArray[i] != '9') {
                charArray[i] = charArray[j] = '9';
                k -= 2;
            }
        }
        return new string(charArray);
    }

    static void Main()
    {
        string s = "19495";
        int k = 3;

        Console.WriteLine("\"" + maxPalindrome(s, k)
                          + "\"");
    }
}
JavaScript
function maxPalindrome(s, k)
{
    let n = s.length;
    let replacements = 0;

    // Count changes needed to make the string a palindrome.
    for (let i = 0, j = n - 1; i < j; i++, j--) {
        if (s[i] !== s[j]) {
            replacements++;

            // -1 if required changes exceed k.
            if (replacements > k)
                return "-1";
        }
    }

    // Maximize the palindrome using the remaining changes.
    let sArray = s.split("");

    for (let i = 0, j = n - 1; i <= j && k > 0; i++, j--) {

        // Maximize the middle digit for odd length.
        if (i === j) {
            sArray[i] = "9";
        }

        // Handle different mirror digits.
        else if (sArray[i] !== sArray[j]) {

            // Use one extra change to make both digits 9.
            if (k - replacements >= 1
                && Math.max(Number(sArray[i]),
                            Number(sArray[j]))
                       !== 9) {

                sArray[i] = sArray[j] = "9";
                replacements--;
                k -= 2;
            }

            // Otherwise, make both digits equal to the
            // larger digit.
            else {
                let larger = Math.max(Number(sArray[i]),
                                      Number(sArray[j]));

                sArray[i] = sArray[j] = String(larger);
                replacements--;
                k--;
            }
        }

        // Make an equal pair 9 if two extra changes are
        // available.
        else if (k - replacements >= 2
                 && sArray[i] !== "9") {
            sArray[i] = sArray[j] = "9";
            k -= 2;
        }
    }

    return sArray.join("");
}

// Driver Code
let s = "19495";
let k = 3;

console.log(`"${maxPalindrome(s, k)}"`);

Output
"99999"
Comment