Minimum Deletions to Make String Balanced (Easy Explanation)

If youโ€™re doing your LeetCode daily streak and today you hit Question 1653 โ€” โ€œMinimum Deletions to Make String Balancedโ€, this one is all about turning a messy mix of a and b into a โ€œcleanโ€ order with the fewest deletions.

Letโ€™s break it down like a human would, not like a textbook.


What does โ€œbalancedโ€ mean?

Youโ€™re given a string s containing only:

  • a
  • b

A string is balanced if all a characters come before any b characters.

So these are balanced โœ…:

  • "aaaa"
  • "aaabbb"
  • "bbb" (yes โ€” no a after b, so itโ€™s fine)

These are NOT balanced โŒ:

  • "ba" (because thereโ€™s a b before an a)
  • "aababbab" (because a appears after some b)

Another way to remember it:

A string is balanced if it has no "ba" pattern.


Goal

Delete the minimum number of characters (any positions you want) so the final string becomes balanced.


Quick examples

Example 1

Input: s = "aababbab"
Output: 2
You can delete 2 characters to make something like "aaabbb".

Example 2

Input: s = "bbaaaaabb"
Output: 2
Delete two bโ€™s at the start (or some aโ€™s in the middle), and it becomes balanced.


Key insight (the โ€œahaโ€ moment)

While scanning the string from left to right:

  • Every time you see a b, itโ€™s fine โ€” b can sit on the right side of a balanced string.
  • Every time you see an a after youโ€™ve already seen some bโ€™s, you have a conflict (a "ba" situation).

When that happens, you have only two logical choices:

  1. Delete this a
    โ†’ cost: deletions + 1
  2. Delete all previous bโ€™s (so this a is no longer โ€œafter a bโ€)
    โ†’ cost: countB (number of b seen so far)

So at every problematic a, we choose the cheaper option:

deletions = min(deletions + 1, countB)

Thatโ€™s the whole solution.


One-pass Greedy/DP Approach (Best for Interviews)

What we track

  • countB: how many bโ€™s weโ€™ve seen so far
  • deletions: minimum deletions needed up to the current position

Step-by-step logic

For each character:

  • If itโ€™s 'b':
    countB += 1
  • If itโ€™s 'a':
    deletions = min(deletions + 1, countB)

This works because weโ€™re always keeping the best possible answer for the prefix weโ€™ve processed.


Time and space complexity

  • Time: O(n) (single pass)
  • Space: O(1) (constant extra memory)

Perfect for large inputs.


Clean code solutions

โœ… Python (LeetCode-ready)

class Solution:
    def minimumDeletions(self, s: str) -> int:
        countB = 0
        deletions = 0

        for ch in s:
            if ch == 'b':
                countB += 1
            else:  # ch == 'a'
                deletions = min(deletions + 1, countB)

        return deletions

โœ… Java

class Solution {
    public int minimumDeletions(String s) {
        int countB = 0;
        int deletions = 0;

        for (int i = 0; i < s.length(); i++) {
            char ch = s.charAt(i);
            if (ch == 'b') {
                countB++;
            } else { // 'a'
                deletions = Math.min(deletions + 1, countB);
            }
        }
        return deletions;
    }
}

โœ… C++

class Solution {
public:
    int minimumDeletions(string s) {
        int countB = 0;
        int deletions = 0;

        for (char ch : s) {
            if (ch == 'b') {
                countB++;
            } else { // 'a'
                deletions = min(deletions + 1, countB);
            }
        }
        return deletions;
    }
};

Mini walkthrough (to make it stick)

Take: s = "ba"

  • Start: countB=0, deletions=0
  • See 'b' โ†’ countB=1
  • See 'a' โ†’ conflict:
    • delete 'a' โ†’ deletions + 1 = 1
    • delete previous 'b' โ†’ countB = 1
    • choose min โ†’ deletions = 1

Answer: 1 โœ…


Common mistakes people make

  • Thinking you need to โ€œrebuild the stringโ€ โ€” you donโ€™t.
  • Using nested loops (goes O(nยฒ) and can TLE).
  • Confusing the balanced condition (itโ€™s all a before b, not the other way around).

FAQ

Is this dynamic programming or greedy?

Itโ€™s basically DP compressed into two variables. The update rule is DP-like, but it behaves greedily because we always choose the cheapest fix at each step.

Why is "bbb" balanced even with no a?

Because the rule is only: no a should appear after a b. If there are no aโ€™s, nothing violates that.

Can I solve it with prefix/suffix counts?

Yes. You can compute:

  • prefix count of b
  • suffix count of a
    and try every split. Itโ€™s still O(n) but uses extra arrays unless optimized.