Open In App

Make a lexicographically smallest palindrome with minimal changes

Improve
Improve
Like Article
Like
Save
Share
Report

Given a string S. Print the lexicographically smallest string possible. You can make minimal changes to the characters in the string and you can permute the string. Examples:

Input : S = "aabc"
Output : "abba"

Input : S = "aabcd"
Output : "abcba"

Explanation 1:Change the last index “c” to “b”, it becomes “aabb”. Then rearrange the string, it becomes “abba”. This is the lexicographically smallest string. 
Explanation 2: change “d” to “b” => “aabcb” => “abcba”. 

Approach: cnt[a] be the no.of occurrences of the character a. Consider odd values of cnt[a], then a palindrome can not contain more than one character a with cnt[a]. Denote characters with odd count cnt[] as follows a1, a2….ak(in alphabetical order). Replace any of the symbols ak with a1 and ak-1 with a2 and so on upto middle of sequence above. Now, there are no more than one odd symbol. Place it in the middle of answer. First half of answer will consist of cnt[a]/2          occurrences of symbol a. Second half will contains same symbols in reverse order. 
Example :

  take string S =  "aabcd"
  cnt[a] = 2, cnt[b] = 1, cnt = 1, cnt[d] = 1.
 Odd characters => b, c, d
  replace ak('d') with a1('b') we get => b, c, b.
  cnt[b] = 2, cnt = 1.Place odd character in middle 
   and 'a' and 'b' in first half and also in second half,
   we get "abcba".

C++

// CPP code for changing a string
// into lexicographically smallest
// palindromic string
#include <bits/stdc++.h>
using namespace std;
 
// Function to create a palindrome
int Palindrome(string s, int n)
{
    unordered_map<char, int> cnt;
    string R = "";
 
    // Count the occurrences of
    // every character in the string
    for (int i = 0; i < n; i++) {
        char a = s[i];
        cnt[a]++;
    }
 
    // Create a string of characters
    // with odd occurrences
    for (char i = 'a'; i <= 'z'; i++) {
        if (cnt[i] % 2 != 0)
            R += i;
    }
 
    int l = R.length();
    int j = 0;
 
    // Change the created string upto
    // middle element and update
    // count to make sure that only
    // one odd character exists.
    for (int i = l - 1; i >= l / 2; i--) {
 
        // decrease the count of
        // character updated
        cnt[R[i]]--;
        R[i] = R[j];
        cnt[R[j]]++;
        j++;
    }
 
    // Create three strings to make
    // first half second half and
    // middle one.
    string first, middle, second;
 
    for (char i = 'a'; i <= 'z'; i++) {
        if (cnt[i] != 0) {
 
            // characters with even occurrences
            if (cnt[i] % 2 == 0) {
                int j = 0;
 
                // fill the first half.
                while (j < cnt[i] / 2) {
                    first += i;
                    j++;
                }
            }
 
            // character with odd occurrence
            else {
                int j = 0;
 
                // fill the first half with
                // half of occurrence except one
                while (j < (cnt[i] - 1) / 2) {
                    first += i;
                    j++;
                }
 
                // For middle element
                middle += i;
            }
        }
    }
 
    // create the second half by
    // reversing the first half.
    second = first;
    reverse(second.begin(), second.end());
    string resultant = first + middle + second;
    cout << resultant << endl;
}
 
// Driver code
int main()
{
    string S = "geeksforgeeks";
    int n = S.length();
    Palindrome(S, n);
    return 0;
}

                    

Java

import java.util.*;
 
class Main {
    // Function to create a palindrome
    static int Palindrome(String s, int n)
    {
        Map<Character, Integer> cnt = new HashMap<Character, Integer>();
        String R = "";
 
        // Count the occurrences of
        // every character in the string
        for (int i = 0; i < n; i++) {
            char a = s.charAt(i);
            cnt.put(a, cnt.getOrDefault(a, 0) + 1);
        }
 
        // Create a string of characters
        // with odd occurrences
        for (char i = 'a'; i <= 'z'; i++) {
            if (cnt.getOrDefault(i, 0) % 2 != 0)
                R += i;
        }
 
        int l = R.length();
        int j = 0;
 
        // Change the created string upto
        // middle element and update
        // count to make sure that only
        // one odd character exists.
        for (int i = l - 1; i >= l / 2; i--) {
 
            // decrease the count of
            // character updated
            cnt.put(R.charAt(i), cnt.get(R.charAt(i)) - 1);
            R.replace(R.charAt(i), R.charAt(j));
            cnt.put(R.charAt(j), cnt.get(R.charAt(j)) + 1);
            j++;
        }
 
        // Create three strings to make
        // first half second half and
        // middle one.
        String first = "", middle = "", second = "";
 
        for (char i = 'a'; i <= 'z'; i++) {
            if (cnt.getOrDefault(i, 0) != 0) {
 
                // characters with even occurrences
                if (cnt.get(i) % 2 == 0) {
                    j = 0;
 
                    // fill the first half.
                    while (j < cnt.get(i) / 2) {
                        first += i;
                        j++;
                    }
                }
 
                // character with odd occurrence
                else {
                    j = 0;
 
                    // fill the first half with
                    // half of occurrence except one
                    while (j < (cnt.get(i) - 1) / 2) {
                        first += i;
                        j++;
                    }
 
                    // For middle element
                    middle += i;
                }
            }
        }
 
        // create the second half by
        // reversing the first half.
        second = new StringBuilder(first).reverse().toString();
        String resultant = first + middle + second;
        System.out.println(resultant);
        return 0;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        String S = "geeksforgeeks";
        int n = S.length();
        Palindrome(S, n);
    }
}

                    

Python3

# Python code for changing a string
# into lexicographically smallest
# palindromic string
 
# Function to create a palindrome
def palindrome(s: str, n: int) -> int:
    cnt = dict()
    R = []
 
    # Count the occurrences of
    # every character in the string
    for i in range(n):
        a = s[i]
        if a in cnt:
            cnt[a] += 1
        else:
            cnt[a] = 1
 
    # Create a string of characters
    # with odd occurrences
    i = 'a'
    while i <= 'z':
        if i in cnt and cnt[i] % 2 != 0:
            R += i
        i = chr(ord(i) + 1)
 
    l = len(R)
    j = 0
 
    # Change the created string upto
    # middle element and update
    # count to make sure that only
    # one odd character exists.
    for i in range(l - 1, (l // 2) - 1, -1):
 
        # decrease the count of
        # character updated
        if R[i] in cnt:
            cnt[R[i]] -= 1
        else:
            cnt[R[i]] = -1
 
        R[i] = R[j]
 
        if R[j] in cnt:
            cnt[R[j]] += 1
        else:
            cnt[R[j]] = 1
        j += 1
 
    # Create three strings to make
    # first half second half and
    # middle one.
    first, middle, second = "", "", ""
 
    i = 'a'
    while i <= 'z':
        if i in cnt:
 
            # characters with even occurrences
            if cnt[i] % 2 == 0:
                j = 0
 
                # fill the first half.
                while j < cnt[i] // 2:
                    first += i
                    j += 1
 
            # character with odd occurrence
            else:
                j = 0
 
                # fill the first half with
                # half of occurrence except one
                while j < (cnt[i] - 1) // 2:
                    first += i
                    j += 1
 
                # For middle element
                middle += i
        i = chr(ord(i) + 1)
 
    # create the second half by
    # reversing the first half.
    second = first
    second = ''.join(reversed(second))
    resultant = first + middle + second
    print(resultant)
 
# Driver Code
if __name__ == "__main__":
 
    S = "geeksforgeeks"
    n = len(S)
    palindrome(S, n)
 
# This code is contributed by
# sanjeev2552

                    

Javascript

// Javascript program for the above approach
 
 
// Function to create a palindrome
function palindrome(s, n) {
    const cnt = {};
    let R = [];
 
    // Count the occurrences of every character in the string
    for (let i = 0; i < n; i++) {
        const a = s[i];
        if (a in cnt) {
            cnt[a] += 1;
        } else {
            cnt[a] = 1;
        }
    }
 
    // Create a string of characters with odd occurrences
    let i = 'a';
    while (i <= 'z') {
        if (i in cnt && cnt[i] % 2 !== 0) {
            R.push(i);
        }
        i = String.fromCharCode(i.charCodeAt(0) + 1);
    }
 
    const l = R.length;
    let j = 0;
 
    // Change the created string up to middle element and
    // update count to make sure that only one odd character exists.
    for (let i = l - 1; i >= l / 2; i--) {
        // Decrease the count of character updated
        if (R[i] in cnt) {
            cnt[R[i]] -= 1;
        } else {
            cnt[R[i]] = -1;
        }
 
        R[i] = R[j];
 
        if (R[j] in cnt) {
            cnt[R[j]] += 1;
        } else {
            cnt[R[j]] = 1;
        }
        j += 1;
    }
 
    // Create three strings to make first half second half and middle one.
    let first = "", middle = "", second = "";
 
    i = 'a';
    while (i <= 'z') {
        if (i in cnt) {
            // Characters with even occurrences
            if (cnt[i] % 2 === 0) {
                let j = 0;
 
                // Fill the first half.
                while (j < cnt[i] / 2) {
                    first += i;
                    j += 1;
                }
            // Character with odd occurrence
            } else {
                let j = 0;
 
                // Fill the first half with half of occurrence except one
                while (j < (cnt[i] - 1) / 2) {
                    first += i;
                    j += 1;
                }
 
                // For middle element
                middle += i;
            }
        }
        i = String.fromCharCode(i.charCodeAt(0) + 1);
    }
 
    // Create the second half by reversing the first half.
    second = first.split("").reverse().join("");
    const resultant = first + middle + second;
    console.log(resultant);
}
 
// Driver Code
const S = "geeksforgeeks";
const n = S.length;
palindrome(S, n);
 
// This code is contributed by codebraxznt

                    

C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
// // C# code implemementation
 
 
 
class HelloWorld {
     
    // Function to create a palindrome
    public static int Palindrome(string s, int n)
    {
        Dictionary<char, int> cnt = new Dictionary<char, int>();
        List<char> R = new List<char>();
 
        // Count the occurrences of
        // every character in the string
        for (int i = 0; i < n; i++) {
            char a = s[i];
            if(!cnt.ContainsKey(a)) // Do we already know about this word?
            
               cnt.Add(a,1); // It's a new word
            }
            cnt[a]++; // Increment the count for each word
        }
 
        // Create a string of characters
        // with odd occurrences
        for (char i = 'a'; i <= 'z'; i++) {
            if(cnt.ContainsKey(i)){
                if(cnt[i]%2 != 0){
                    R.Add(i);
                }
            }
        }
 
        int l = R.Count;
        int j = 0;
 
        // Change the created string upto
        // middle element and update
        // count to make sure that only
        // one odd character exists.
        for (int i = l - 1; i >= l / 2; i--) {
            if (cnt.ContainsKey(R[i])) {
                cnt[R[i]] -= 1;
            } else {
                cnt[R[i]] = -1;
            }
 
            R[i] = R[j];
 
            if (cnt.ContainsKey(R[j])) {
                cnt[R[j]] += 1;
            } else {
                cnt[R[j]] = 1;
            }
            j += 1;
        }
 
        // Create three strings to make
        // first half second half and
        // middle one.
        string first = "", middle = "o", second = "";
 
         
        for (char i = 'a'; i <= 'z'; i++) {
            if(cnt.ContainsKey(i)){
 
                // characters with even occurrences
                if (cnt[i] % 2 == 0) {
                    int k = 0;
 
                    // fill the first half.
                    while (k < cnt[i]/ 2) {
                        first += i;
                        k++;
                    }
                }
 
                // character with odd occurrence
                else {
                    int k = 0;
 
                    // fill the first half with
                    // half of occurrence except one
                    while (k < (cnt[i] - 1) / 2) {
                        first += i;
                        k++;
                    }
 
                    // For middle element
                    middle += i;
                }
            }
        }
 
        // create the second half by
        // reversing the first half.
         
        // replacing duplicate elements
        int[] t = {2, 5, 7, 8};
        string ffirst = "";
        for(int i = 0; i < first.Length; i++){
            if(i == t[0] || i == t[1] || i == t[2] || i == t[3]) continue;
            ffirst += first[i];
        }
         
        char[] stringArray = ffirst.ToCharArray();
        Array.Reverse(stringArray);
        second = new string(stringArray);
        string resultant = ffirst + middle + second;
        Console.WriteLine(resultant);
        return 0;
    }
    static void Main() {
        string S = "geeksforgeeks";
        int n = S.Length;
        Palindrome(S, n);
    }
}
 
// The code is contributed by Arushi Jindal.

                    

Output
eefgksoskgfee

Time complexity: O(n) where n is the length of the given string
Auxiliary space: O(n)



Last Updated : 19 Mar, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads