Maximize value of Palindrome by rearranging characters of a Substring
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
An approach using BitMasking:
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; // Function to find the maximum possible // palindromic value 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; } // Function to find the maximum value // between two given string 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); } // Generate all possible valid palindrome // and maximize the value among // all palindrome string maxPalindrome(string& s) { // Initialize an array visited[] for // storing the mask that has occurred // previously vector<int> visited(5555, -1); int mask = 0, n = s.size(); string result = "0"; // Iterate over the string for (int i = 0; i < n; i++) { // Calculate the mask by toggling // the corresponding bit of current // character in the string. mask ^= (1 << (s[i] - '0')); // Check if mask is zero, means // occurrence of all character are // even. So, this is a possible // way to rearrange character // to palindrome if (mask == 0) { // Maximize the palindrome value result = maxOfBoth(result, maxValue(s, 0, i)); } // Toggle all possible bit // one by one for (int j = 0; j <= 9; j++) { // Calculate the new Mask by // toggling the corresponding // bit of current mask int newMask = mask; newMask ^= (1 << j); // Check if mask is zero, // means occurrence of all // character are even except // one. So, this is a // possible way to rearrange // character to palindrome if (newMask == 0) { // Maximize the palindrome // value in result result = maxOfBoth(result, maxValue(s, 0, i)); } // Check if this new mask has // occurred before else if (visited[newMask] != -1) { // Maximize the palindrome // value result = maxOfBoth( result, maxValue(s, visited[newMask] + 1, i)); } } // Check if the current mask is // not been visited yet // then, Mark the current mask // visited at index i if (visited[mask] == -1) { visited[mask] = i; } } // Return the result return result; } // Drive code int main() { string s = "25242459"; // Function call cout << maxPalindrome(s); return 0; }
Java
import java.util.*; class Main { // Function to find the maximum possible // palindromic value 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; } // Function to find the maximum value // between two given string 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); } // Generate all possible valid palindrome // and maximize the value among // all palindrome public static String maxPalindrome(String s) { // Initialize an array visited[] for // storing the mask that has occurred // previously int[] visited = new int[5555]; Arrays.fill(visited, -1); int mask = 0, n = s.length(); String result = "0"; // Iterate over the string for (int i = 0; i < n; i++) { // Calculate the mask by toggling // the corresponding bit of current // character in the string. mask ^= (1 << (s.charAt(i) - '0')); // Check if mask is zero, means // occurrence of all character are // even. So, this is a possible // way to rearrange character // to palindrome if (mask == 0) { // Maximize the palindrome value result = maxOfBoth(result, maxValue(s, 0, i)); } // Toggle all possible bit // one by one for (int j = 0; j <= 9; j++) { // Calculate the new Mask by // toggling the corresponding // bit of current mask int newMask = mask; newMask ^= (1 << j); // Check if mask is zero, // means occurrence of all // character are even except // one. So, this is a // possible way to rearrange // character to palindrome if (newMask == 0) { // Maximize the palindrome // value in result result = maxOfBoth(result, maxValue(s, 0, i)); } // Check if this new mask has // occurred before else if (visited[newMask] != -1) { // Maximize the palindrome // value result = maxOfBoth( result, maxValue(s, visited[newMask] + 1, i)); } } // Check if the current mask is // not been visited yet // then, Mark the current mask // visited at index i if (visited[mask] == -1) { visited[mask] = i; } } // Return the result return result; } // Driver code public static void main(String[] args) { String s = "25242459"; // Function call System.out.println(maxPalindrome(s)); } } // This code is contributed by Tapesh(tapeshdua420)
Python3
# Function to find the maximum possible # palindromic value 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 # Function to find the maximum value # between two given string 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 # Generate all possible valid palindrome # and maximize the value among # all palindrome def maxPalindrome(s): # Initialize an array visited[] for # storing the mask that has occurred # previously visited = [-1 for _ in range(5555)] mask = 0 n = len(s) result = "0" # Iterate over the string for i in range(n): # Calculate the mask by toggling # the corresponding bit of current # character in the string. mask ^= (1 << (ord(s[i]) - ord('0'))) # Check if mask is zero, means # occurrence of all character are # even. So, this is a possible # way to rearrange character # to palindrome if mask == 0: # Maximize the palindrome value result = maxOfBoth(result, maxValue(s, 0, i)) # Toggle all possible bit # one by one for j in range(10): # Calculate the new Mask by # toggling the corresponding # bit of current mask newMask = mask ^ (1 << j) # Check if mask is zero, # means occurrence of all # character are even except # one. So, this is a # possible way to rearrange # character to palindrome if newMask == 0: # Maximize the palindrome # value in result result = maxOfBoth(result, maxValue(s, 0, i)) # Check if this new mask has # occurred before elif visited[newMask] != -1: # Maximize the palindrome # value result = maxOfBoth(result, maxValue( s, visited[newMask] + 1, i)) # Check if the current mask is # not been visited yet # then, Mark the current mask # visited at index i if visited[mask] == -1: visited[mask] = i # Return the result return result # Function call print(maxPalindrome("25242459")) # This code is contributed by Tapesh(tapeshdua420)
C#
using System; using System.Collections.Generic; using System.Linq; class Program { // Function to find the maximum possible // palindromic value 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; } // Function to find the maximum value // between two given string 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); } // Generate all possible valid palindrome // and maximize the value among // all palindrome static string maxPalindrome(string s) { // Initialize an array visited[] for // storing the mask that has occurred // previously 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"; // Iterate over the string for (int i = 0; i < n; i++) { // Calculate the mask by toggling // the corresponding bit of current // character in the string. mask ^= (1 << (s[i] - '0')); // Check if mask is zero, means // occurrence of all character are // even. So, this is a possible // way to rearrange character // to palindrome if (mask == 0) // Maximize the palindrome value result = maxOfBoth(result, maxValue(s, 0, i)); // Toggle all possible bit // one by one for (int j = 0; j <= 9; j++) { // Calculate the new Mask by // toggling the corresponding // bit of current mask int newMask = mask; newMask ^= (1 << j); // Check if mask is zero, // means occurrence of all // character are even except // one. So, this is a // possible way to rearrange // character to palindrome if (newMask == 0) // Maximize the palindrome // value in result result = maxOfBoth(result, maxValue(s, 0, i)); // Check if this new mask has // occurred before else if (visited[newMask] != -1) // Maximize the palindrome // value result = maxOfBoth( result, maxValue(s, visited[newMask] + 1, i)); } // Check if the current mask is // not been visited yet // then, Mark the current mask // visited at index i if (visited[mask] == -1) visited[mask] = i; } // Return the result return result; } // Driver code static void Main() { string s = "25242459"; // Function call Console.WriteLine(maxPalindrome(s)); } } // This code is contributed by Tapesh(tapeshdua420)
Javascript
// Function to find the maximum possible // palindromic value 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 to find the maximum value // between two given string 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); } } // Generate all possible valid palindrome // and maximize the value among // all palindrome function maxPalindrome(s) { // Initialize an array visited[] for // storing the mask that has occurred // previously var visited = new Array(5555).fill(-1); var mask = 0; var n = s.length; var result = "0"; // Iterate over the string for (var i = 0; i < n; i++) { // Calculate the mask by toggling // the corresponding bit of current // character in the string. mask ^= (1 << (s[i].charCodeAt() - '0'.charCodeAt())); // Check if mask is zero, means // occurrence of all character are // even. So, this is a possible // way to rearrange character // to palindrome if (mask == 0) { // Maximize the palindrome value result = maxOfBoth(result, maxValue(s, 0, i)); } // Toggle all possible bit // one by one for (var j = 0; j < 10; j++) { // Calculate the new Mask by // toggling the corresponding // bit of current mask var newMask = mask ^ (1 << j); // Check if mask is zero, // means occurrence of all // character are even except // one. So, this is a // possible way to rearrange // character to palindrome if (newMask == 0) { // Maximize the palindrome // value in result result = maxOfBoth(result, maxValue(s, 0, i)); } // Check if this new mask has // occurred before else if (visited[newMask] != -1) { // Maximize the palindrome // value result = maxOfBoth(result, maxValue(s, visited[newMask] + 1, i)); } } // Check if the current mask is // not been visited yet // then, Mark the current mask // visited at index i if (visited[mask] == -1) { visited[mask] = i; } } // Return the result return result; } // Function call console.log(maxPalindrome("25242459")) // This code is contributed by Tapesh(tapeshdua420)
5429245
Time Complexity: O(N2 * log(N))
Auxiliary Space: O(N)
Please Login to comment...