Given a string S of length N (1 ? N ? 103) that consists of a digit from ‘0’ to ‘9’, the task is to find the maximum value of palindrome that could be generated by rearranging characters of a substring.
Examples:
Input: S = “91242459” Output: 42524 Explanation: Rearrange the substring ‘24245’ to form a palindrome. This will give the maximum value of the palindrome.
Input: S = “25242459” Output: 5429245
The idea is to find the largest substring that we can rearrange to form palindrome. As in a palindrome every character must be present even number of times except for a maximum of 1 element. So XOR of all elements of substring must be 0 or same with the one with odd occurrences. So we can use bitmasking to find the largest valid substring.
After then among all largest valid substrings we would generate the largest palindrome that are possible by rearranging the characters of the valid substring and keep track of the largest generated palindrome.
Follow the steps below to implement the above idea:
- Initialize an array visited[] for storing the mask that has occurred previously
- Iterate over the string:
- Calculate the current mask by toggling the corresponding bit of the current character in the string.
- Check if the mask is zero, which means the occurrence of all characters is even. So, this is a possible way to rearrange character to palindrome
- Maximize the palindrome value.
- Toggle all possible bits one by one
- Assign new mask = mask and toggle the corresponding bit in the new mask
- Check if the new mask is zero, which means the occurrence of all characters is even except that one. So, this is a possible way to rearrange character to palindrome
- Maximize the palindrome value in the result
- Check if this new mask has occurred before
- Maximize the palindrome value
- Check if the current mask is not been visited yet then, mark the current mask visited at index i.
- Return the result.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
string maxValue(string& s, int i, int j)
{
map< char , int > mp;
for ( int k = i; k <= j; k++) {
mp[s[k]]++;
}
string res = "" , oddChar = "" ;
for ( auto it = mp.rbegin(); it != mp.rend(); it++) {
if (it->second % 2 != 0) {
oddChar = it->first;
}
else {
res += string(it->second / 2, it->first);
}
}
string reverseRes = res;
reverse(reverseRes.begin(), reverseRes.end());
string a = res + oddChar + reverseRes;
return a;
}
string maxOfBoth(string s1, string s2)
{
if (s1.size() > s2.size())
return s1;
else if (s2.size() > s1.size())
return s2;
return ((s1 > s2) ? s1 : s2);
}
string maxPalindrome(string& s)
{
vector< int > visited(5555, -1);
int mask = 0, n = s.size();
string result = "0" ;
for ( int i = 0; i < n; i++) {
mask ^= (1 << (s[i] - '0' ));
if (mask == 0) {
result = maxOfBoth(result, maxValue(s, 0, i));
}
for ( int j = 0; j <= 9; j++) {
int newMask = mask;
newMask ^= (1 << j);
if (newMask == 0) {
result
= maxOfBoth(result, maxValue(s, 0, i));
}
else if (visited[newMask] != -1) {
result = maxOfBoth(
result,
maxValue(s, visited[newMask] + 1, i));
}
}
if (visited[mask] == -1) {
visited[mask] = i;
}
}
return result;
}
int main()
{
string s = "25242459" ;
cout << maxPalindrome(s);
return 0;
}
|
Java
import java.util.*;
class Main
{
public static String maxValue(String s, int i, int j)
{
Map<Character, Integer> mp
= new TreeMap<Character, Integer>(
Collections.reverseOrder());
for ( int k = i; k <= j; k++) {
if (mp.containsKey(s.charAt(k))) {
mp.put(s.charAt(k),
mp.get(s.charAt(k)) + 1 );
}
else {
mp.put(s.charAt(k), 1 );
}
}
String res = "" , oddChar = "" ;
for (Map.Entry<Character, Integer> entry :
mp.entrySet()) {
if (entry.getValue() % 2 != 0 ) {
oddChar
= Character.toString(entry.getKey());
}
else {
res += new String(
new char [entry.getValue() / 2 ])
.replace( "\0" ,
Character.toString(
entry.getKey()));
}
}
String reverseRes
= new StringBuilder(res).reverse().toString();
return res + oddChar + reverseRes;
}
public static String maxOfBoth(String s1, String s2)
{
if (s1.length() > s2.length())
return s1;
else if (s2.length() > s1.length())
return s2;
return ((s1.compareTo(s2) > 0 ) ? s1 : s2);
}
public static String maxPalindrome(String s)
{
int [] visited = new int [ 5555 ];
Arrays.fill(visited, - 1 );
int mask = 0 , n = s.length();
String result = "0" ;
for ( int i = 0 ; i < n; i++)
{
mask ^= ( 1 << (s.charAt(i) - '0' ));
if (mask == 0 )
{
result
= maxOfBoth(result, maxValue(s, 0 , i));
}
for ( int j = 0 ; j <= 9 ; j++)
{
int newMask = mask;
newMask ^= ( 1 << j);
if (newMask == 0 )
{
result = maxOfBoth(result,
maxValue(s, 0 , i));
}
else if (visited[newMask] != - 1 )
{
result = maxOfBoth(
result,
maxValue(s, visited[newMask] + 1 ,
i));
}
}
if (visited[mask] == - 1 ) {
visited[mask] = i;
}
}
return result;
}
public static void main(String[] args)
{
String s = "25242459" ;
System.out.println(maxPalindrome(s));
}
}
|
Python3
def maxValue(s, i, j):
mp = {}
for k in range (i, j + 1 ):
if s[k] not in mp:
mp[s[k]] = 1
else :
mp[s[k]] + = 1
res = ""
oddChar = ""
for key in sorted (mp.keys(), reverse = True ):
if mp[key] % 2 ! = 0 :
oddChar = key
else :
res + = (mp[key] / / 2 ) * key
reverseRes = res[:: - 1 ]
a = res + oddChar + reverseRes
return a
def maxOfBoth(s1, s2):
if len (s1) > len (s2):
return s1
elif len (s2) > len (s1):
return s2
else :
return s1 if s1 > s2 else s2
def maxPalindrome(s):
visited = [ - 1 for _ in range ( 5555 )]
mask = 0
n = len (s)
result = "0"
for i in range (n):
mask ^ = ( 1 << ( ord (s[i]) - ord ( '0' )))
if mask = = 0 :
result = maxOfBoth(result, maxValue(s, 0 , i))
for j in range ( 10 ):
newMask = mask ^ ( 1 << j)
if newMask = = 0 :
result = maxOfBoth(result, maxValue(s, 0 , i))
elif visited[newMask] ! = - 1 :
result = maxOfBoth(result, maxValue(
s, visited[newMask] + 1 , i))
if visited[mask] = = - 1 :
visited[mask] = i
return result
print (maxPalindrome( "25242459" ))
|
C#
using System;
using System.Collections.Generic;
using System.Linq;
class Program {
static string maxValue( string s, int i, int j)
{
var mp = new SortedDictionary< char , int >();
for ( int k = i; k <= j; k++) {
if (mp.ContainsKey(s[k])) {
mp[s[k]] += 1;
}
else {
mp[s[k]] = 1;
}
}
string res = "" , oddChar = "" ;
foreach ( var entry in mp.Reverse())
{
if (entry.Value % 2 != 0) {
oddChar = entry.Key.ToString();
}
else {
res += new String( new char [entry.Value / 2])
.Replace( "\0" ,
entry.Key.ToString());
}
}
string reverseRes
= new string (res.Reverse().ToArray());
return res + oddChar + reverseRes;
}
static string maxOfBoth( string s1, string s2)
{
if (s1.Length > s2.Length)
return s1;
else if (s2.Length > s1.Length)
return s2;
return ((s1.CompareTo(s2) > 0) ? s1 : s2);
}
static string maxPalindrome( string s)
{
int [] visited = new int [5555];
for ( int i = 0; i < visited.Length; i++)
visited[i] = -1;
int mask = 0, n = s.Length;
string result = "0" ;
for ( int i = 0; i < n; i++) {
mask ^= (1 << (s[i] - '0' ));
if (mask == 0)
result
= maxOfBoth(result, maxValue(s, 0, i));
for ( int j = 0; j <= 9; j++) {
int newMask = mask;
newMask ^= (1 << j);
if (newMask == 0)
result = maxOfBoth(result,
maxValue(s, 0, i));
else if (visited[newMask] != -1)
result = maxOfBoth(
result,
maxValue(s, visited[newMask] + 1,
i));
}
if (visited[mask] == -1)
visited[mask] = i;
}
return result;
}
static void Main()
{
string s = "25242459" ;
Console.WriteLine(maxPalindrome(s));
}
}
|
Javascript
function maxValue(s, i, j) {
var mp = {};
for ( var k = i; k <= j; k++) {
if (mp[s[k]]) {
mp[s[k]]++;
} else {
mp[s[k]] = 1;
}
}
var items = Object.keys(mp).map(
(key) => { return [key, mp[key]] });
items.sort(
(first, second) => { return second[0] - first[0] }
);
var res = "" , oddChar = "" ;
for ( var it of items) {
if (it[1] % 2 != 0) {
oddChar = it[0];
} else {
res += new Array(it[1] / 2 + 1).join(it[0]);
}
}
var reverseRes = res.split( "" ).reverse().join( "" );
return res + oddChar + reverseRes;
}
function maxOfBoth(s1, s2) {
if (s1.length > s2.length) {
return s1;
} else if (s2.length > s1.length) {
return s2;
} else {
return (s1 > s2 ? s1 : s2);
}
}
function maxPalindrome(s) {
var visited = new Array(5555).fill(-1);
var mask = 0;
var n = s.length;
var result = "0" ;
for ( var i = 0; i < n; i++) {
mask ^= (1 << (s[i].charCodeAt() - '0' .charCodeAt()));
if (mask == 0) {
result = maxOfBoth(result, maxValue(s, 0, i));
}
for ( var j = 0; j < 10; j++) {
var newMask = mask ^ (1 << j);
if (newMask == 0) {
result = maxOfBoth(result, maxValue(s, 0, i));
}
else if (visited[newMask] != -1) {
result = maxOfBoth(result, maxValue(s, visited[newMask] + 1, i));
}
}
if (visited[mask] == -1) {
visited[mask] = i;
}
}
return result;
}
console.log(maxPalindrome( "25242459" ))
|
Time Complexity: O(N2 * log(N)) Auxiliary Space: O(N)
|