Solution: Palindrome Permutation
Let's solve the Palindrome Permutation problem using the Knowing What to Track pattern.
Statement#
For a given string, st, find whether or not a permutation of this string is a palindrome. You should return TRUE if such a permutation is possible and FALSE if it isn’t possible.
Constraints:
-
st.length - The string will contain lowercase English letters.
Solution#
So far, you’ve probably brainstormed some approaches and have an idea of how to solve this problem. Let’s explore some of these approaches and figure out which one to follow based on considerations such as time complexity and any implementation constraints.
Naive approach#
The naive solution is to first compute all possible permutations of a given string and then iterate over each permutation to see if it’s a palindrome. We can use two pointers to traverse the computed permutation from the beginning and the end simultaneously, comparing each character at every step. If the two pointers point to the same character until they cross each other, the string is a palindrome.
The number of possible permutations for a string of length is , and it requires iterating through the characters to construct each permutation. Therefore, it will take time to generate all these permutations. Then, for each permutation, we need to check whether it is a palindrome. Checking this condition requires iterating through the permutation once, which takes time. Therefore, the overall time complexity of this naive approach is . The space complexity is because we need to store all the permutations.
Optimized approach using frequency counting#
This is the stereotypical example of a problem whose naive solution is very inefficient, yet by identifying a few key properties of the problem, we are able to devise a solution with superior time and space complexity measures. In this case, there are three key observations:
- In a palindrome of even length, all the characters occur an even number of times. For example, in the palindrome “aaaabbaaaa”, “a” occurs four times and “b” occurs twice.
- In a palindrome of odd length, the character in the middle of the string appears once, and all the others occur an even number of times. For example, in the palindrome “aaabaaa”, “a” occurs six times and “b” occurs once.
- The observations above are true for all the permutations of a palindrome. For example, “aaaaaaaabb” is a permutation of “aaaabbaaaa” in which “a” still occurs four times and “b” occurs twice.
So, to decide whether or not a given string has a permutation that is a palindrome, all we need to do is count the number of times each character appears in it and then check how many characters appear an odd number of times.
- If no characters appear an odd number of times, then the string is of even length and has a permutation that is a palindrome.
- If only one character appears an odd number of times, then the string is of odd length and has a permutation that is a palindrome.
- If more than one character appears an odd number of times, then the string does not have a permutation that is a palindrome.
The slides below illustrate the working of our proposed solution:
1 of 13
2 of 13
3 of 13
4 of 13
5 of 13
6 of 13
7 of 13
8 of 13
9 of 13
10 of 13
11 of 13
12 of 13
13 of 13
Note: In the following section, we will gradually build the solution. Alternatively, you can skip straight to just the code.
Step-by-step solution construction#
Building on the above idea, the first step in our algorithm is to traverse the input string and populate a hash map with characters and their frequencies. If a character is already present, we’ll increment its frequency by . Otherwise, we set its frequency .
Next, we traverse the hash map and count the characters with an odd number of occurrences. We keep track of this number using a variable count that is incremented every time a character with an odd frequency is encountered.
Lastly, we check if count is greater than . If yes, no permutation is a palindrome. Otherwise, at least one of the permutations of the given string is a palindrome.
Just the code#
Here’s the complete solution to this problem:
Solution summary#
To recap, the solution to this problem can be divided into the following parts:
- Populate a hash map with string characters and their frequencies.
- Count the characters with frequency .
- If
count, return FALSE. Otherwise, return TRUE.
Time complexity#
There are two parts in this solution. In the first part, we iterate over a string of characters, checking their presence in a hash map and adding/updating the hash map as we go. The average time complexity for looking up values in a hash map is . The worst case time complexity for looking up values in a hash map is , where is the number of elements in the hash map. Since the string only contains lowercase English letters, there are distinct characters in this case.
Thus, the average time complexity of the first part of the solution is while the worst case time complexity is . In this scenario, the worst case time complexity is , which simplifies to .
In the second part, our loop iterates at most times. Hence the time complexity of the second part is .
In summary, our solution’s average and worst case time complexity is .
Space complexity#
The hash map can grow up to if all the characters in the string are distinct. However, the number of distinct characters is bounded and so is the space complexity. So, the space complexity is .
Palindrome Permutation
Valid Anagram