Maximum Palindromes After Operations solution and explanation
8 more videos on this problem
3035. Maximum Palindromes After Operations | Greedy | Palindrome | String | SortingAryan Mittal · 18:34 · 4K views
3035. Maximum Palindromes After Operations | Weekly Leetcode 384codingMohan · 22:48 · 886 views
Maximum Palindromes After Operations - Leetcode 3035CheatCode Ninja · 12:49 · 827 views
3035 Maximum Palindromes After Operations || Even and Odd Pairs ✅Ayush Rao · 10:13 · 730 views
3035. Maximum Palindromes After Operations (Leetcode Medium)Programming Live with Larry · 13:19 · 712 views
Leetcode 3035: Maximum Palindromes After OperationsAlgorithms Casts · 20:52 · 185 views
3035. Maximum Palindromes After Operations || Weekly Contest 384 || C++Priyanshi Porwal · 25:01 · 146 views
Maximum Palindromes After Operations - LEETCODE WEEKLY CONTEST 384Joyjit Codes · 9:09 · 125 views
LeetCode 3035 - Maximum Palindromes after Operations - PythonAlpha-Code · 18:51 · 68 views
The problem
You are given a 0-indexed string array words having length n and containing 0-indexed strings.
You are allowed to perform the following operation any number of times (including zero):
- Choose integers
i,j,x, andysuch that0 <= i, j < n,0 <= x < words[i].length,0 <= y < words[j].length, and swap the characterswords[i][x]andwords[j][y].
Return an integer denoting the maximum number of palindromes words can contain, after performing some operations.
Note: i and j may be equal during an operation.
Example 1:
Input: words = ["abbb","ba","aa"] Output: 3 Explanation: In this example, one way to get the maximum number of palindromes is: Choose i = 0, j = 1, x = 0, y = 0, so we swap words[0][0] and words[1][0]. words becomes ["bbbb","aa","aa"]. All strings in words are now palindromes. Hence, the maximum number of palindromes achievable is 3.
Example 2:
Input: words = ["abc","ab"] Output: 2 Explanation: In this example, one way to get the maximum number of palindromes is: Choose i = 0, j = 1, x = 1, y = 0, so we swap words[0][1] and words[1][0]. words becomes ["aac","bb"]. Choose i = 0, j = 0, x = 1, y = 2, so we swap words[0][1] and words[0][2]. words becomes ["aca","bb"]. Both strings are now palindromes. Hence, the maximum number of palindromes achievable is 2.
Example 3:
Input: words = ["cd","ef","a"] Output: 1 Explanation: In this example, there is no need to perform any operation. There is one palindrome in words "a". It can be shown that it is not possible to get more than one palindrome after any number of operations. Hence, the answer is 1.
Constraints:
1 <= words.length <= 10001 <= words[i].length <= 100words[i]consists only of lowercase English letters.
Approach overview
Problem Overview: You receive an array of strings. Characters can be swapped between any strings. After performing any number of swaps, determine the maximum number of strings that can be rearranged into palindromes.
The key observation: swaps make character positions irrelevant across words. Only the total character counts matter. A string of length k needs k/2 character pairs to form mirrored positions. If the length is odd, one extra character can sit in the center.
Approach 1: Utilize Frequency Counts (O(n log n) time, O(1) space)
Count the total frequency of each character across all words using a simple array or hash map from the hash table family of techniques. From these counts, compute the number of available pairs (freq // 2). Each palindrome requires len(word) // 2 pairs. Sort the word lengths in ascending order using a sorting strategy, then greedily allocate pairs to shorter words first. This works because shorter words require fewer resources, allowing you to build more palindromes overall. If enough pairs exist for a word, construct the palindrome conceptually and subtract the used pairs. The remaining characters automatically cover the middle position for odd lengths. This approach is efficient because character counts are bounded (26 lowercase letters), so the extra memory stays constant.
Approach 2: Construct Palindrome Greedily (O(n log n) time, O(1) space)
This approach models the process more directly. First aggregate all character counts using a array of size 26. Convert those counts into a pool of available pairs. Next sort the strings by length. For each string, attempt to construct its palindrome by consuming pairs from the pool. A string of length L needs L/2 mirrored pairs; the center character (if L is odd) can always be filled because leftover characters exist once pairs are broken down. The greedy rule remains the same: allocate pairs to the smallest strings first so that pair resources are distributed to the maximum number of strings.
Recommended for interviews: The frequency-count + greedy allocation approach is what interviewers usually expect. It shows you recognize that cross-string swaps eliminate positional constraints and reduce the problem to pair counting. Starting with raw counting demonstrates understanding, while the sorted greedy allocation shows algorithmic optimization using greedy reasoning.
Approach 1: Approach 1: Utilize Frequency Counts
To determine the maximum number of palindromes, you can start by checking the frequency of each character across all words. A string can be rearranged into a palindrome if at most one character has an odd frequency while others have even frequencies.
Therefore, by calculating the frequency of characters, you can determine the maximum potential palindromes by freely swapping characters to achieve evenly distributed counts across the words.
def max_palindromes(words):
from collections import Counter
total_count = Counter()
for word in words:
total_count.update(word)
odd_count = sum(count % 2 for count in total_count.values())
return len(words) - odd_count // 2
# Example usage
words = ['abbb', 'ba', 'aa']
print(max_palindromes(words)) # Output: 3function maxPalindromes(words) {
let totalCount = Array(26).fill(0);
for (let word of words) {
for (let char of word) {
totalCount[char.charCodeAt(0) - 'a'.charCodeAt(0)]++;
}
}
let oddCount = totalCount.reduce((count, frequency) => count + (frequency % 2), 0);
return words.length - Math.floor(oddCount / 2);
}
// Example usage
const words = ['abbb', 'ba', 'aa'];
console.log(maxPalindromes(words)); // Output: 3This solution uses a counter to aggregate the frequency of each character across all words. The sum of characters with odd frequencies indicates how many swaps are minimally required to potentially form a palindrome. Since two words can share a character swap to even out odd frequencies, the number of palindromes is maximized by leveraging these swaps.
Time Complexity: O(n * m), where n is the number of words and m is the average length of the words.
Space Complexity: O(1), since we're using a fixed size array to count frequencies of 26 letters.
Approach 2: Approach 2: Construct Palindrome Greedily
In this method, you attempt to form a palindrome for each word independently and count how many times that is possible. If a word already forms a palindrome, it contributes directly to the count. If not, determine if character swaps between all available words can resolve the imbalance.
import java.util.*;
public class MaxPalindromes {
public static int maxPalindromes(String[] words) {
int n = words.length;
int res = 0;
Map<Character, Integer> freqMap = new HashMap<>();
for (String word: words) {
boolean isPalindrome = true;
for (int i = 0; i < word.length() / 2; i++) {
if (word.charAt(i) != word.charAt(word.length() - 1 - i)) {
isPalindrome = false;
break;
}
}
if (isPalindrome) {
res++;
}
for (char ch: word.toCharArray()) {
freqMap.put(ch, freqMap.getOrDefault(ch, 0) + 1);
}
}
int oddCount = 0;
for (int freq: freqMap.values()) {
if (freq % 2 != 0) oddCount++;
}
return res + (n - res - oddCount / 2);
}
public static void main(String[] args) {
String[] words = {"abbb", "ba", "aa"};
System.out.println(maxPalindromes(words)); // Output: 3
}
}#include <iostream>
#include <unordered_map>
using namespace std;
int maxPalindromes(vector<string>& words) {
unordered_map<char, int> freqMap;
int res = 0;
for (string word : words) {
bool isPalindrome = true;
for (int i = 0; i < word.size() / 2; i++) {
if (word[i] != word[word.size() - 1 - i]) {
isPalindrome = false;
break;
}
}
if (isPalindrome) {
res++;
}
for (char ch : word) {
freqMap[ch]++;
}
}
int oddCount = 0;
for (auto const &pair : freqMap) {
if (pair.second % 2 != 0) oddCount++;
}
return res + (words.size() - res - oddCount / 2);
}
int main() {
vector<string> words = {"abbb", "ba", "aa"};
cout << maxPalindromes(words) << endl; // Output: 3
return 0;
}The Java version here first checks if any word is a palindrome naturally. For non-palindrome words, it count frequencies and odd counts just like before.
Time Complexity: O(n * m), with n, m as number of words and average length, respectively.
Space Complexity: O(1) for the character frequency map size determined by a fixed character set.
Approach 3: Default Approach
function maxPalindromesAfterOperations(words: string[]): number {
let s: number = 0;
let mask: number = 0;
for (const w of words) {
s += w.length;
for (const c of w) {
mask ^= 1 << (c.charCodeAt(0) - 'a'.charCodeAt(0));
}
}
s -= (mask.toString(2).match(/1/g) || []).length;
words.sort((a, b) => a.length - b.length);
let ans: number = 0;
for (const w of words) {
s -= Math.floor(w.length / 2) * 2;
if (s < 0) {
break;
}
ans++;
}
return ans;
}func maxPalindromesAfterOperations(words []string) (ans int) {
var s, mask int
for _, w := range words {
s += len(w)
for _, c := range w {
mask ^= 1 << (c - 'a')
}
}
s -= bits.OnesCount(uint(mask))
sort.Slice(words, func(i, j int) bool {
return len(words[i]) < len(words[j])
})
for _, w := range words {
s -= len(w) / 2 * 2
if s < 0 {
break
}
ans++
}
return
}Complexity comparison
| Approach | Complexity |
|---|---|
| Approach 1: Utilize Frequency Counts | Time Complexity: O(n * m), where n is the number of words and m is the average length of the words. |
| Approach 2: Construct Palindrome Greedily | Time Complexity: O(n * m), with n, m as number of words and average length, respectively. |
| Default Approach | – |
Complexity analysis
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Utilize Frequency Counts | O(n log n) | O(1) | General case. Efficient when you only need pair counts and want a simple greedy allocation. |
| Construct Palindrome Greedily | O(n log n) | O(1) | When reasoning about actually building palindromes step‑by‑step helps clarify the greedy allocation. |
Frequently asked questions
Is Maximum Palindromes After Operations easy or hard?
Maximum Palindromes After Operations is generally classified as a medium difficulty problem. The challenge comes from recognizing that swaps allow characters to be pooled globally, reducing the task to counting pairs and applying a greedy distribution strategy.
Maximum Palindromes After Operations Python/Java solution
Most implementations first compute a frequency array of size 26, count how many character pairs exist, then sort the word lengths. Python solutions typically use collections.Counter, while Java implementations use an int[26] array. Both follow the same greedy pair allocation logic.
How to solve Maximum Palindromes After Operations in O(n)?
Pure O(n) is difficult because most solutions sort string lengths to apply the greedy strategy. However, the core operations—frequency counting and pair calculation—run in linear time over the characters. With bounded length constraints or counting sort on lengths, the sorting step can be reduced close to linear time.
What is the best approach for Maximum Palindromes After Operations?
The most efficient approach counts the total frequency of characters across all words and converts them into usable pairs. After sorting word lengths, greedily assign pairs to the smallest words first. This ensures the maximum number of palindromes can be formed while keeping time complexity around O(n log n).
Is Maximum Palindromes After Operations asked at Google/Amazon/Meta?
Greedy counting problems similar to this appear frequently in interviews at companies like Amazon, Google, and Meta. The pattern of converting character frequencies into usable pairs and allocating them optimally is a common string and greedy interview concept.
What data structure is used in Maximum Palindromes After Operations?
The solution primarily uses a fixed-size frequency array (or hash table) to store character counts. Sorting is applied to string lengths, and a simple greedy allocation determines how many palindromes can be formed.
What is the time complexity of Maximum Palindromes After Operations?
The optimal solution runs in O(n log n) time where n is the number of strings. Counting character frequencies takes O(total characters), and sorting the string lengths dominates the runtime. Space complexity is O(1) because only a fixed 26‑character frequency array is required.
