{x}
blog image

Make The String Great

Given a string s of lower and upper case English letters.

A good string is a string which doesn't have two adjacent characters s[i] and s[i + 1] where:

  • 0 <= i <= s.length - 2
  • s[i] is a lower-case letter and s[i + 1] is the same letter but in upper-case or vice-versa.

To make the string good, you can choose two adjacent characters that make the string bad and remove them. You can keep doing this until the string becomes good.

Return the string after making it good. The answer is guaranteed to be unique under the given constraints.

Notice that an empty string is also good.

 

Example 1:

Input: s = "leEeetcode"
Output: "leetcode"
Explanation: In the first step, either you choose i = 1 or i = 2, both will result "leEeetcode" to be reduced to "leetcode".

Example 2:

Input: s = "abBAcC"
Output: ""
Explanation: We have many possible scenarios, and all lead to the same answer. For example:
"abBAcC" --> "aAcC" --> "cC" --> ""
"abBAcC" --> "abBA" --> "aA" --> ""

Example 3:

Input: s = "s"
Output: "s"

 

Constraints:

  • 1 <= s.length <= 100
  • s contains only lower and upper case English letters.

Solution Explanation

The problem asks to create a "good" string from an input string s. A "good" string doesn't have any adjacent characters where one is a lowercase letter and the other is its uppercase counterpart (or vice versa). The solution uses a stack-based approach to efficiently solve this.

Approach:

  1. Initialization: We initialize an empty stack, stk. This stack will store the characters of the resulting "good" string.

  2. Iteration: We iterate through each character c in the input string s.

  3. Stack Check: For each character, we check the following conditions:

    • If the stack stk is empty or the absolute difference between the ASCII values of the top element of the stack and the current character c is not 32, then we push c onto the stack. The ASCII difference of 32 signifies a lowercase and uppercase pair (e.g., 'a' and 'A').

    • If the absolute difference is 32, it means we have found a pair that violates the "good" string condition. In this case, we pop the top element from the stack (removing the conflicting pair).

  4. Result: After iterating through all the characters in s, the stack stk contains the characters of the "good" string. We convert the stack into a string and return it.

Time and Space Complexity Analysis:

  • Time Complexity: O(N), where N is the length of the input string s. We iterate through the string once, and stack operations (push and pop) take constant time.

  • Space Complexity: O(N) in the worst case. The stack could potentially hold all the characters of the input string if there are no conflicting pairs to remove. In the best case (all pairs are removed), the space complexity would be O(1).

Code Explanation (Python):

class Solution:
    def makeGood(self, s: str) -> str:
        stk = []  # Initialize an empty stack
        for c in s:  # Iterate through each character in the input string
            if not stk or abs(ord(stk[-1]) - ord(c)) != 32:  # Check if stack is empty or characters are not a conflicting pair
                stk.append(c)  # Push the character onto the stack
            else:
                stk.pop()  # Pop the top element (conflicting pair)
        return "".join(stk)  # Convert the stack to a string and return it
 

The other languages (Java, C++, Go) follow the same logic; they differ only in syntax and data structures used to implement the stack. The core algorithm remains the same.