Given a string s, consisting of lowercase Latin characters [a-z]. Find out all the possible palindromes that can be generated using the letters of the string and print them in lexicographical order.
Examples:
Input: s = "abbab"
Output: [abbba, babab]
Explanation: abbba and babab are two possible string that are palindrome.Input: s = "abc"
Output: []
Explanation: No permutation is palindromic.
Try It Yourself
Table of Content
[Naive Approach] Generate All Permutations - O(n * n!) Time and O(n!) Space
The idea is to generate every distinct permutation of the given string and check whether it is a palindrome.
Working of Approach:
- Sort the string so that next_permutation() generates distinct permutations in lexicographical order.
- Generate every permutation of the string.
- Check whether the current permutation is a palindrome.
- If it is a palindrome, store it in the answer.
- Return all palindromic permutations.
#include <bits/stdc++.h>
using namespace std;
// Function to check whether a string is palindrome.
bool isPalindrome(string &str)
{
int i = 0, j = str.size() - 1;
while (i < j)
{
if (str[i] != str[j])
return false;
i++;
j--;
}
return true;
}
// Function to find all palindromic permutations.
vector<string> allPalindromes(string &s)
{
vector<string> res;
// Sort the string to generate distinct permutations.
sort(s.begin(), s.end());
// Generate all distinct permutations.
do
{
// If the current permutation is a palindrome,
// store it in the result.
if (isPalindrome(s))
res.push_back(s);
} while (next_permutation(s.begin(), s.end()));
return res;
}
int main()
{
string s = "abbab";
vector<string> res = allPalindromes(s);
cout << "[";
for (int i = 0; i < res.size(); i++)
{
cout << res[i];
if (i + 1 < res.size())
cout << ", ";
}
cout << "]";
return 0;
}
import java.util.*;
class GFG {
// Function to check whether a string is palindrome.
static boolean isPalindrome(String str)
{
int i = 0, j = str.length() - 1;
while (i < j) {
if (str.charAt(i) != str.charAt(j))
return false;
i++;
j--;
}
return true;
}
// Function to generate the next lexicographical
// permutation.
static boolean nextPermutation(char[] arr)
{
int i = arr.length - 2;
while (i >= 0 && arr[i] >= arr[i + 1])
i--;
if (i < 0)
return false;
int j = arr.length - 1;
while (arr[j] <= arr[i])
j--;
char temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
int left = i + 1, right = arr.length - 1;
while (left < right) {
temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
left++;
right--;
}
return true;
}
// Function to find all palindromic permutations.
static ArrayList<String> allPalindromes(String s)
{
ArrayList<String> res = new ArrayList<>();
char[] arr = s.toCharArray();
Arrays.sort(arr);
do {
String curr = new String(arr);
if (isPalindrome(curr))
res.add(curr);
} while (nextPermutation(arr));
return res;
}
public static void main(String[] args)
{
String s = "abbab";
ArrayList<String> res = allPalindromes(s);
System.out.print("[");
for (int i = 0; i < res.size(); i++) {
System.out.print(res.get(i));
if (i + 1 < res.size())
System.out.print(", ");
}
System.out.print("]");
}
}
from itertools import permutations
# Function to check whether a string is palindrome.
def isPalindrome(str):
i = 0
j = len(str) - 1
while i < j:
if str[i] != str[j]:
return False
i += 1
j -= 1
return True
# Function to find all palindromic permutations.
def allPalindromes(s):
res = []
# Generate all distinct permutations.
permuted = sorted(set(permutations(s)))
for p in permuted:
p_str = ''.join(p)
# If the current permutation is a palindrome,
# store it in the result.
if isPalindrome(p_str):
res.append(p_str)
return res
if __name__ == '__main__':
s = "abbab"
res = allPalindromes(s)
print('[', end='')
for i in range(len(res)):
print(res[i], end='')
if i + 1 < len(res):
print(', ', end='')
print(']')
using System;
using System.Collections.Generic;
class GFG {
// Function to check whether a string is palindrome.
static bool IsPalindrome(string str)
{
int i = 0, j = str.Length - 1;
while (i < j) {
if (str[i] != str[j])
return false;
i++;
j--;
}
return true;
}
// Function to generate the next lexicographical
// permutation.
static bool NextPermutation(char[] arr)
{
int i = arr.Length - 2;
while (i >= 0 && arr[i] >= arr[i + 1])
i--;
if (i < 0)
return false;
int j = arr.Length - 1;
while (arr[j] <= arr[i])
j--;
char temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
int left = i + 1, right = arr.Length - 1;
while (left < right) {
temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
left++;
right--;
}
return true;
}
// Function to find all palindromic permutations.
static List<string> allPalindromes(string s)
{
List<string> res = new List<string>();
char[] arr = s.ToCharArray();
Array.Sort(arr);
do {
string curr = new string(arr);
if (IsPalindrome(curr))
res.Add(curr);
} while (NextPermutation(arr));
return res;
}
static void Main()
{
string s = "abbab";
List<string> res = allPalindromes(s);
Console.Write("[");
for (int i = 0; i < res.Count; i++) {
Console.Write(res[i]);
if (i + 1 < res.Count)
Console.Write(", ");
}
Console.Write("]");
}
}
// Function to check whether a string is palindrome.
function isPalindrome(str)
{
let i = 0, j = str.length - 1;
while (i < j) {
if (str[i] !== str[j])
return false;
i++;
j--;
}
return true;
}
// Function to generate the next lexicographical
// permutation.
function nextPermutation(arr)
{
let i = arr.length - 2;
while (i >= 0 && arr[i] >= arr[i + 1])
i--;
if (i === -1)
return false;
let j = arr.length - 1;
while (arr[j] <= arr[i])
j--;
swap(arr, i, j);
let left = i + 1, right = arr.length - 1;
while (left < right) {
swap(arr, left, right);
left++;
right--;
}
return true;
}
function swap(arr, i, j)
{
let temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
// Function to find all palindromic permutations.
function allPalindromes(s)
{
let res = [];
// Sort the string to generate distinct permutations.
let arr = s.split("").sort();
do {
let curr = arr.join("");
// If the current permutation is a palindrome,
// store it in the result.
if (isPalindrome(curr))
res.push(curr);
} while (nextPermutation(arr));
return res;
}
// Driver Code
let s = "abbab";
let res = allPalindromes(s);
process.stdout.write("[");
for (let i = 0; i < res.length; i++) {
process.stdout.write(res[i]);
if (i + 1 < res.length)
process.stdout.write(", ");
}
process.stdout.write("]");
Output
[abbba, babab]
[Expected Approach] Generate Half String Permutations - O((n/2)! * n) Time and O(n) Space
The idea is to generate permutations of only the first half of the palindrome and construct the remaining half using symmetry.
Working of Approach:
- Count the frequency of every character.
- If more than one character has an odd frequency, no palindrome is possible.
- Build the first half using half of every character's frequency.
- Generate all distinct permutations of the half string.
- Append the middle character (if any) and the reverse of the half to form complete palindromes.
Let us understand with an example:
Input: s = "abbab"
- Count the frequency of each character: a = 2, b = 3. Since only one character (b) has an odd frequency, a palindrome is possible.
- Construct the first half as "ab" (a/2 = 1, b/2 = 1) and store 'b' as the middle character.
- First permutation of half = "ab" -> Reverse = "ba" -> Palindrome = "ab" + "b" + "ba" = "abbba".
- Next permutation of half = "ba" -> Reverse = "ab" -> Palindrome = "ba" + "b" + "ab" = "babab".
- No more permutations are possible, so return [abbba, babab].
#include <bits/stdc++.h>
using namespace std;
// Function to check if a palindrome can be formed.
bool isPalindromePossible(string &s)
{
int n = s.size();
if (n == 0)
return false;
vector<int> hash(26, 0);
// Count the frequency of each character.
for (char ch : s)
hash[ch - 'a']++;
int cnt = 0;
// Count the characters having odd frequency.
for (int i = 0; i < 26; i++)
{
if (hash[i] & 1)
cnt++;
}
// For odd length, exactly one character
// should have odd frequency.
if ((n & 1) && cnt == 1)
return true;
// For even length, no character
// should have odd frequency.
if (n % 2 == 0 && cnt == 0)
return true;
return false;
}
// Function to find all possible palindromic strings.
vector<string> allPalindromes(string &s)
{
vector<string> res;
int n = s.size();
// If palindrome cannot be formed,
// return empty vector.
if (!isPalindromePossible(s))
return res;
string half = "";
vector<int> hash(26, 0);
char mid;
// Count the frequency of each character.
for (char ch : s)
hash[ch - 'a']++;
// Construct the first half of the palindrome.
for (int i = 0; i < 26; i++)
{
if (hash[i] & 1)
mid = char(i + 'a');
half += string(hash[i] / 2, char(i + 'a'));
}
// Generate all distinct permutations
// of the first half.
do
{
string cur = half;
string rev = half;
// Add the middle character
// for odd length strings.
if (n & 1)
cur += mid;
// Append the reverse of the first half.
reverse(rev.begin(), rev.end());
cur += rev;
res.push_back(cur);
} while (next_permutation(half.begin(), half.end()));
return res;
}
int main()
{
string s = "abbab";
vector<string> res = allPalindromes(s);
cout << "[";
for (int i = 0; i < res.size(); i++)
{
cout << res[i];
if (i + 1 < res.size())
cout << ", ";
}
cout << "]";
return 0;
}
import java.util.*;
class GFG {
// Function to check if a palindrome can be formed.
static boolean isPalindromePossible(String s)
{
int n = s.length();
if (n == 0)
return false;
int[] hash = new int[26];
// Count the frequency of each character.
for (int i = 0; i < n; i++)
hash[s.charAt(i) - 'a']++;
int cnt = 0;
// Count the characters having odd frequency.
for (int i = 0; i < 26; i++) {
if ((hash[i] & 1) == 1)
cnt++;
}
// For odd length, exactly one character
// should have odd frequency.
if ((n & 1) == 1 && cnt == 1)
return true;
// For even length, no character
// should have odd frequency.
if (n % 2 == 0 && cnt == 0)
return true;
return false;
}
// Function to generate the next lexicographical
// permutation.
static boolean nextPermutation(char[] arr)
{
int i = arr.length - 2;
while (i >= 0 && arr[i] >= arr[i + 1])
i--;
if (i < 0)
return false;
int j = arr.length - 1;
while (arr[j] <= arr[i])
j--;
char temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
int left = i + 1, right = arr.length - 1;
while (left < right) {
temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
left++;
right--;
}
return true;
}
// Function to find all possible palindromic strings.
static ArrayList<String> allPalindromes(String s)
{
ArrayList<String> res = new ArrayList<>();
int n = s.length();
// If palindrome cannot be formed,
// return empty list.
if (!isPalindromePossible(s))
return res;
StringBuilder half = new StringBuilder();
int[] hash = new int[26];
char mid = 0;
// Count the frequency of each character.
for (int i = 0; i < n; i++)
hash[s.charAt(i) - 'a']++;
// Construct the first half of the palindrome.
for (int i = 0; i < 26; i++) {
if ((hash[i] & 1) == 1)
mid = (char)(i + 'a');
for (int j = 0; j < hash[i] / 2; j++)
half.append((char)(i + 'a'));
}
char[] arr = half.toString().toCharArray();
do {
String firstHalf = new String(arr);
StringBuilder cur
= new StringBuilder(firstHalf);
// Add the middle character
// for odd length strings.
if ((n & 1) == 1)
cur.append(mid);
// Append the reverse of the first half.
cur.append(
new StringBuilder(firstHalf).reverse());
res.add(cur.toString());
} while (nextPermutation(arr));
return res;
}
public static void main(String[] args)
{
String s = "abbab";
ArrayList<String> res = allPalindromes(s);
System.out.print("[");
for (int i = 0; i < res.size(); i++) {
System.out.print(res.get(i));
if (i + 1 < res.size())
System.out.print(", ");
}
System.out.print("]");
}
}
# Function to check if a palindrome can be formed.
def isPalindromePossible(s):
n = len(s)
if n == 0:
return False
hash = [0] * 26
# Count the frequency of each character.
for ch in s:
hash[ord(ch) - ord('a')] += 1
cnt = 0
# Count the characters having odd frequency.
for i in range(26):
if hash[i] & 1:
cnt += 1
# For odd length, exactly one character
# should have odd frequency.
if (n & 1) and cnt == 1:
return True
# For even length, no character
# should have odd frequency.
if n % 2 == 0 and cnt == 0:
return True
return False
# Function to generate the next lexicographical permutation.
def nextPermutation(arr):
i = len(arr) - 2
while i >= 0 and arr[i] >= arr[i + 1]:
i -= 1
if i < 0:
return False
j = len(arr) - 1
while arr[j] <= arr[i]:
j -= 1
arr[i], arr[j] = arr[j], arr[i]
left, right = i + 1, len(arr) - 1
while left < right:
arr[left], arr[right] = arr[right], arr[left]
left += 1
right -= 1
return True
# Function to find all possible palindromic strings.
def allPalindromes(s):
res = []
n = len(s)
# If palindrome cannot be formed,
# return empty list.
if not isPalindromePossible(s):
return res
hash = [0] * 26
half = []
mid = ""
# Count the frequency of each character.
for ch in s:
hash[ord(ch) - ord('a')] += 1
# Construct the first half of the palindrome.
for i in range(26):
if hash[i] & 1:
mid = chr(i + ord('a'))
half.extend([chr(i + ord('a'))] * (hash[i] // 2))
# Generate all distinct permutations
# of the first half.
while True:
firstHalf = "".join(half)
cur = firstHalf
# Add the middle character
# for odd length strings.
if n & 1:
cur += mid
# Append the reverse of the first half.
cur += firstHalf[::-1]
res.append(cur)
if not nextPermutation(half):
break
return res
if __name__ == "__main__":
s = "abbab"
res = allPalindromes(s)
print("[", end="")
for i in range(len(res)):
print(res[i], end="")
if i + 1 < len(res):
print(", ", end="")
print("]")
using System;
using System.Collections.Generic;
using System.Text;
class GFG {
// Function to check if a palindrome can be formed.
static bool IsPalindromePossible(string s)
{
int n = s.Length;
if (n == 0)
return false;
int[] hash = new int[26];
// Count the frequency of each character.
foreach(char ch in s) hash[ch - 'a']++;
int cnt = 0;
// Count the characters having odd frequency.
for (int i = 0; i < 26; i++) {
if ((hash[i] & 1) == 1)
cnt++;
}
// For odd length, exactly one character
// should have odd frequency.
if ((n & 1) == 1 && cnt == 1)
return true;
// For even length, no character
// should have odd frequency.
if (n % 2 == 0 && cnt == 0)
return true;
return false;
}
// Function to generate the next lexicographical
// permutation.
static bool NextPermutation(char[] arr)
{
int i = arr.Length - 2;
while (i >= 0 && arr[i] >= arr[i + 1])
i--;
if (i < 0)
return false;
int j = arr.Length - 1;
while (arr[j] <= arr[i])
j--;
char temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
int left = i + 1, right = arr.Length - 1;
while (left < right) {
temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
left++;
right--;
}
return true;
}
// Function to find all possible palindromic strings.
static List<string> allPalindromes(string s)
{
List<string> res = new List<string>();
int n = s.Length;
// If palindrome cannot be formed,
// return empty list.
if (!IsPalindromePossible(s))
return res;
StringBuilder half = new StringBuilder();
int[] hash = new int[26];
char mid = '\0';
// Count the frequency of each character.
foreach(char ch in s) hash[ch - 'a']++;
// Construct the first half of the palindrome.
for (int i = 0; i < 26; i++) {
if ((hash[i] & 1) == 1)
mid = (char)(i + 'a');
for (int j = 0; j < hash[i] / 2; j++)
half.Append((char)(i + 'a'));
}
char[] arr = half.ToString().ToCharArray();
do {
string firstHalf = new string(arr);
StringBuilder cur
= new StringBuilder(firstHalf);
// Add the middle character
// for odd length strings.
if ((n & 1) == 1)
cur.Append(mid);
// Append the reverse of the first half.
char[] rev = firstHalf.ToCharArray();
Array.Reverse(rev);
cur.Append(new string(rev));
res.Add(cur.ToString());
} while (NextPermutation(arr));
return res;
}
static void Main()
{
string s = "abbab";
List<string> res = allPalindromes(s);
Console.Write("[");
for (int i = 0; i < res.Count; i++) {
Console.Write(res[i]);
if (i + 1 < res.Count)
Console.Write(", ");
}
Console.Write("]");
}
}
// Function to check if a palindrome can be formed.
function isPalindromePossible(s)
{
let n = s.length;
if (n === 0)
return false;
let hash = new Array(26).fill(0);
// Count the frequency of each character.
for (let ch of s)
hash[ch.charCodeAt(0) - "a".charCodeAt(0)]++;
let cnt = 0;
// Count the characters having odd frequency.
for (let i = 0; i < 26; i++) {
if (hash[i] & 1)
cnt++;
}
// For odd length, exactly one character
// should have odd frequency.
if ((n & 1) && cnt === 1)
return true;
// For even length, no character
// should have odd frequency.
if (n % 2 === 0 && cnt === 0)
return true;
return false;
}
// Function to generate the next lexicographical
// permutation.
function nextPermutation(arr)
{
let i = arr.length - 2;
while (i >= 0 && arr[i] >= arr[i + 1])
i--;
if (i < 0)
return false;
let j = arr.length - 1;
while (arr[j] <= arr[i])
j--;
[arr[i], arr[j]] = [ arr[j], arr[i] ];
let left = i + 1, right = arr.length - 1;
while (left < right) {
[arr[left], arr[right]] = [ arr[right], arr[left] ];
left++;
right--;
}
return true;
}
// Function to find all possible palindromic strings.
function allPalindromes(s)
{
let res = [];
let n = s.length;
// If palindrome cannot be formed,
// return empty array.
if (!isPalindromePossible(s))
return res;
let hash = new Array(26).fill(0);
let half = [];
let mid = "";
// Count the frequency of each character.
for (let ch of s)
hash[ch.charCodeAt(0) - "a".charCodeAt(0)]++;
// Construct the first half of the palindrome.
for (let i = 0; i < 26; i++) {
if (hash[i] & 1)
mid = String.fromCharCode(i
+ "a".charCodeAt(0));
for (let j = 0; j < Math.floor(hash[i] / 2); j++)
half.push(
String.fromCharCode(i + "a".charCodeAt(0)));
}
// Generate all distinct permutations
// of the first half.
do {
let firstHalf = half.join("");
let cur = firstHalf;
// Add the middle character
// for odd length strings.
if (n & 1)
cur += mid;
// Append the reverse of the first half.
cur += [...firstHalf ].reverse().join("");
res.push(cur);
} while (nextPermutation(half));
return res;
}
// Driver Code
let s = "abbab";
let res = allPalindromes(s);
process.stdout.write("[");
for (let i = 0; i < res.length; i++) {
process.stdout.write(res[i]);
if (i + 1 < res.length)
process.stdout.write(", ");
}
process.stdout.write("]");
Output
[abbba, babab]