You are given a string s
consisting only of characters 'a'
and 'b'
.
You can delete any number of characters in s
to make s
balanced. s
is balanced if there is no pair of indices (i,j)
such that i < j
and s[i] = 'b'
and s[j]= 'a'
.
Return the minimum number of deletions needed to make s
balanced.
Example 1:
Input: s = "aababbab" Output: 2 Explanation: You can either: Delete the characters at 0-indexed positions 2 and 6 ("aababbab" -> "aaabbb"), or Delete the characters at 0-indexed positions 3 and 6 ("aababbab" -> "aabbbb").
Example 2:
Input: s = "bbaaaaabb" Output: 2 Explanation: The only solution is to delete the first two characters.
Constraints:
1 <= s.length <= 105
s[i]
is 'a'
or 'b'
.This problem asks for the minimum number of deletions needed to make a string consisting of 'a' and 'b' characters balanced. A balanced string has no 'b' appearing before an 'a'. Several approaches can solve this efficiently.
This approach uses dynamic programming to build a solution iteratively. We define f[i]
as the minimum deletions needed to balance the first i
characters of the string.
State Transition:
f[i] = f[i-1]
. We increment a counter b
to track the number of 'b's encountered so far.f[i] = f[i-1] + 1
f[i] = b
(we delete all preceding 'b's to make the string balanced)We choose the minimum of these two options.
Time Complexity: O(n), where n is the length of the string. We iterate through the string once. Space Complexity: O(n) in the basic DP implementation. However, it can be optimized to O(1) as shown in the code examples below.
class Solution:
def minimumDeletions(self, s: str) -> int:
n = len(s)
ans = 0 # Optimized to O(1) space
b = 0
for i in range(n):
if s[i] == 'b':
b += 1
else:
ans = min(ans + 1, b)
return ans
The optimized Python code above eliminates the need for a DP array by directly maintaining the minimum deletions (ans
) and the count of 'b's (b
). Other languages demonstrate similar optimizations.
This is a more efficient and intuitive approach. We iterate through the string, maintaining two counters:
lb
: Counts the number of 'b's encountered so far.ra
: Counts the number of 'a's remaining in the suffix of the string (initially, the total number of 'a's).For each character:
ra
.lb
.ans
) as min(ans, lb + ra)
.Time Complexity: O(n) Space Complexity: O(1)
class Solution:
def minimumDeletions(self, s: str) -> int:
lb, ra = 0, s.count('a')
ans = len(s) # Initialize with maximum possible deletions
for c in s:
ra -= c == 'a'
ans = min(ans, lb + ra)
lb += c == 'b'
return ans
This approach directly calculates the minimum deletions without explicitly building a DP table.
A stack-based approach is possible but less efficient than the previous two. The idea is to push characters onto a stack. When you encounter a 'b' followed by an 'a', you pop the 'b' and increment the deletion count. However, this approach requires O(n) space for the stack, making it less optimal than the O(1) space solutions above.
Choose either Approach 1 (optimized) or Approach 2 for optimal performance. Approach 2 is generally preferred for its clarity and efficiency. Avoid Approach 3 due to higher space complexity.