Given a string s
. In one step, you can insert any character at any index of the string.
Return the minimum number of steps to make s
a palindrome.
A Palindrome String is one that reads the same backward as well as forward.
Example 1:
Input: s = "zzazz"
Output: 0
Explanation: The string "zzazz" is already a palindrome; we do not need any insertions.
Example 2:
Input: s = "mbadm"
Output: 2
Explanation: The string can be "mbdadbm" or "mdbabdm".
Example 3:
Input: s = "leetcode"
Output: 5
Explanation: Inserting 5 characters, the string becomes "leetcodocteel".
Constraints:
1 <= s.length <= 500
s
consists of lowercase English letters.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 most straightforward, but slow, way to make a string a palindrome is to try inserting characters in every possible place. We check if we can make the string a palindrome after each set of insertions. We find the smallest set of insertions this way.
Here's how the algorithm would work step-by-step:
def minimum_insertion_steps_palindrome_brute_force(input_string):
string_length = len(input_string)
# Check if the string is already a palindrome
if input_string == input_string[::-1]:
return 0
for number_of_insertions in range(1, string_length + 1):
possible_strings = generate_possible_strings(input_string, number_of_insertions)
for possible_string in possible_strings:
# Found a palindrome, return the insertion count
if possible_string == possible_string[::-1]:
return number_of_insertions
return string_length
def generate_possible_strings(input_string, number_of_insertions):
possible_strings = []
generate_strings_recursive(input_string, number_of_insertions, "", possible_strings)
return possible_strings
def generate_strings_recursive(input_string, number_of_insertions, current_string, possible_strings):
if number_of_insertions == 0:
# Base case: append original string and check if valid
combined_string = current_string + input_string
possible_strings.append(combined_string)
return
string_length = len(input_string)
# Iterate through all possible insertion positions
for insertion_index in range(string_length + 1):
for char_code in range(ord('a'), ord('z') + 1):
character_to_insert = chr(char_code)
new_string = input_string[:insertion_index] + character_to_insert + input_string[insertion_index:]
# Reduce insertion count
remaining_string = new_string
generate_strings_recursive(remaining_string, number_of_insertions - 1, "", possible_strings)
The key to solving this efficiently is recognizing the connection to the Longest Common Subsequence (LCS). Instead of brute-forcing insertions, we find the longest sequence that's already a palindrome within the original string. The number of insertions needed is then simply the difference between the original string's length and the length of that palindrome.
Here's how the algorithm would work step-by-step:
def min_insertions(input_string):
string_length = len(input_string)
reversed_string = input_string[::-1]
# Initialize a DP table to store lengths of LCS.
longest_common_subsequence_table = [[0] * (string_length + 1) for _ in range(string_length + 1)]
# Building the dp table in bottom up manner.
for i in range(1, string_length + 1):
for j in range(1, string_length + 1):
# If characters match, increase LCS length.
if input_string[i - 1] == reversed_string[j - 1]:
longest_common_subsequence_table[i][j] = longest_common_subsequence_table[i - 1][j - 1] + 1
else:
# Otherwise, take the max LCS length from previous results.
longest_common_subsequence_table[i][j] = max(longest_common_subsequence_table[i - 1][j], longest_common_subsequence_table[i][j - 1])
# The longest common subsequence length is palindrome.
longest_palindrome_length = longest_common_subsequence_table[string_length][string_length]
# Min insertions equals length diff.
return string_length - longest_palindrome_length
Case | How to Handle |
---|---|
Null or empty string input | Return 0, as an empty string is already a palindrome. |
String with a single character | Return 0, as a single-character string is already a palindrome. |
String with two identical characters | Return 0, as it's already a palindrome. |
String with two different characters | Return 1, as one insertion is required. |
String that is already a palindrome | Return 0, as no insertions are needed. |
String with all identical characters (e.g., 'aaaa') | Return 0, as the string is already a palindrome. |
Very long string exceeding memory limits for dynamic programming table | Consider using an optimized space complexity dynamic programming approach or report that input size is too large. |
String contains unicode or special characters | Ensure the comparison logic handles unicode or special characters correctly based on the problem's assumptions. |