Hello, reader ๐๐ฝ ! Welcome to day 10 of the series on Problem Solving. Through this series, I aim to pick up at least one question everyday and share my approach for solving it.
Today, I will be picking up LeetCode's daily challenge problem: 1328. Break a Palindrome.
๐ค Problem Statement
- Given a palindrome, return the lexicographically smallest word after replacing a single character such that the resulting string is not a palindrome. Return an empty string if you cannot make a string non-palindrome.
- E.g.
- 'abcba' -> There are multiple ways to make this a non-palindrome string. One could be:
bbcba
, orcbcba
, but the lexicographically smallest one isaacba
.
- 'abcba' -> There are multiple ways to make this a non-palindrome string. One could be:
๐ฌ Initial Thought Process
- This problem was pretty straightforward. Yet, I overthought my way through and now, when I look into the first solution I wrote, I roll over and laugh.
- A typical greedy problem (which I'm very ashamed to confess that I did not recognise!).
- But before going over through the intuition behind the algorithm, let me share what I thought.
- First, it was very clear that there's only 1 way the input could not be converted to a non-palindrome => If it was a string of length 1. So I didn't have to worry about this edge case.
I saw the it was given that the string length n was
1 <= n <= 1000
, so I thought of this:- What if I when over through the entire string and tried replacing every character? T
- After I replace each character, I can check if the resultant string is a palindrome, if yes, then I ignore the string.
- If the resultant string is not a palindrome, I can check if it's the smaller than the previous non-palindrome string. If not, then I ignore the string and move on to the next character.
Although the above approach ran for the given test cases, it failed in cases such as
aba
.I went over this algorithm for about an hour and then finally looked into the hints. That's when it hit me that the hint was in
replace exactly one
andlexicographically smallest
.- Since we already know that we need to replace just a single character, the hint is
lexicographically smallest
.- Since the resultant string would also be of the same length as input string, the next clue was in:
A string a is lexicographically smaller than a string b (of the same length) if in the first position where a and b differ, a has a character strictly smaller than the corresponding character in b.
- Since the resultant string would also be of the same length as input string, the next clue was in:
Intuition
- The smallest letter is
a
. The idea is to replace the in the first half (since the 2nd half also has the same letters) of the string a character that isnot a
=>a
. - For e.g. if the palindrome was:
aaccaa
. Here the first character that's not an a (and is also in the range [0,n/2) isc
. So, we replace that with a. Result is:aaacaa
.- This result is smaller than any other character you'd replace before it say:
baccaa
orabccaa
.
- This result is smaller than any other character you'd replace before it say:
- But what if there's no character in the first half that is
not a
? That means the palindrome has all character's asa
. Then it's simple. We keep all thea
's except the last and replace it withb
. - E.g. If the palindrome was:
aaaaa
, then we keep the first 4a
's and replace the lasta
withb
. Result is:aaaab
.- This result is smaller than any other replacements you do to the previous characters.
๐ฉ๐ฝโ๐ป Solution - Greedy
Below is the solution for the above approach:
class Solution { public String breakPalindrome(String palindrome) { if(palindrome == null || palindrome.length() == 0) { return palindrome; } int n = palindrome.length(); // There's no way to make a palindrome of length 1 // to a non palindromic string if(n == 1) { return ""; } int i = 0; // Check only the first half since the // second half has the same characters while(i < n/2) { char ch = palindrome.charAt(i); if(ch != 'a') { return palindrome.substring(0,i) + 'a' + palindrome.substring(i+1); } i++; } return palindrome.substring(0,n-1) + 'b'; } }
Time Complexity: O(n) - n = length of input palindrome string Space: O(1)
Checkout the code on GitHub for this problem: Break a Palindrome.
Conclusion
That's a wrap for today's problem. If you liked my explanation then please do drop a like/ comment. Also, please correct me if I've made any mistakes or if you want me to improve something!
Thank you for reading!