Given a string s
and an integer k
, determine if it is possible to construct k
non-empty palindrome strings using all the characters in s
. Return true
if possible; otherwise, return false
.
Example 1:
Input: s = "annabelle", k = 2
Output: true
Explanation: You can construct two palindromes using all characters in s.
Some possible constructions "anna" + "elble", "anbna" + "elle", "anellena" + "b"
Example 2:
Input: s = "leetcode", k = 3
Output: false
Explanation: It is impossible to construct 3 palindromes using all the characters of s.
Example 3:
Input: s = "true", k = 4
Output: true
Explanation: The only possible solution is to put each character in a separate string.
Constraints:
1 <= s.length <= 10^5
s
consists of lowercase English letters.1 <= k <= 10^5
Can you provide an efficient algorithm to solve this problem, considering both time and space complexity?
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The core idea is to check every possible way to divide a given string into smaller strings. We then check if these smaller strings can be rearranged to form palindromes. If we find a valid arrangement we return true, otherwise we try another one.
Here's how the algorithm would work step-by-step:
def can_construct_k_palindromes_brute_force(input_string, k_substrings):
string_length = len(input_string)
# If the number of substrings is larger than the string length, impossible
if k_substrings > string_length:
return False
# Function to check if a string can form a palindrome
def can_form_palindrome(substring):
character_counts = {}
for character in substring:
character_counts[character] = character_counts.get(character, 0) + 1
odd_count = 0
for count in character_counts.values():
if count % 2 != 0:
odd_count += 1
return odd_count <= 1
# Recursive helper function to generate all possible splits
def find_all_splits(current_index, current_split, all_splits):
if len(current_split) == k_substrings - 1:
# Ensure the last substring is added to the split
last_substring = input_string[current_index:]
if last_substring:
current_split.append(last_substring)
all_splits.append(current_split[:])
current_split.pop()
return
for i in range(current_index + 1, string_length - (k_substrings - 1 - len(current_split)) + 1):
# Construct substring and add it to the current split
substring = input_string[current_index:i]
current_split.append(substring)
find_all_splits(i, current_split, all_splits)
current_split.pop()
all_splits = []
find_all_splits(0, [], all_splits)
# Check if any split consists of palindromable substrings
for split in all_splits:
can_construct = True
for substring in split:
if not can_form_palindrome(substring):
can_construct = False
break
# If all substrings can form a palindrome, we return True
if can_construct:
return True
# If we can't find any valid splits return false
return False
The core idea is to understand that a palindrome string can be formed if it either has all even counts of characters or at most one character with an odd count. The strategy is to count how many characters occur an odd number of times and compare that with the desired number of palindrome strings.
Here's how the algorithm would work step-by-step:
def can_construct_k_palindromes(input_string: str, number_of_palindromes: int) -> bool:
character_counts = {}
for char in input_string:
character_counts[char] = character_counts.get(char, 0) + 1
odd_count = 0
for char in character_counts:
if character_counts[char] % 2 != 0:
odd_count += 1
# If odd count is more than k, impossible
if odd_count > number_of_palindromes:
return False
# If length of string is less than k, impossible
if len(input_string) < number_of_palindromes:
return False
# Otherwise, it is possible
return True
Case | How to Handle |
---|---|
Null or empty string s | Return False if s is null or empty since no palindromes can be formed. |
k is zero or negative | Return False if k is zero or negative as we cannot create zero or negative number of palindromes. |
k is greater than the length of string s | Return False because you can never have more palindromes than the length of the string itself (each char being its own palindrome). |
String s has length 1 and k is greater than 1 | Return False, as you can't break a single character string into more than one palindrome. |
String s has length 1 and k is equal to 1 | Return True, as a single character is a palindrome. |
String s has all unique characters, and k is greater than 1. | Check if the length of s is less than or equal to K since each individual char would be its own palindrome, if not then return false since it is impossible. |
String s has length n, and k is equal to n | Return True if k equals the string length, since each character can form its own single-character palindrome. |
String s has length n, and k equals 1 | Check if the entire string 's' can be a palindrome (if the odd character count is more than 1, then return false). |