1544. Make The String Great

1544. Make The String Great

Problem Solving - Day 38

ยท

4 min read

Hello, reader ๐Ÿ‘‹๐Ÿฝ ! Welcome to day 38 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: 1544. Make The String Great.


๐Ÿค” Problem Statement

  • Given a string s of lower and upper case English letters, return the string after making it good.
  • 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, choose two adjacent characters that make the string bad and remove them. This can be repeatedly done until the string becomes good..

  • An empty string is also good.

  • E.g.:

    • s = "leEeetcode" => "leetcode"
    • s = "abBAcC" => ""

๐Ÿ’ฌ Thought Process - Stack

  • There's a naive approach to solve this problem that takes O(n^2) solution, which I shall not be highlighting here.
  • There's an optimal solution using stack. We traverse the string and keep pushing characters to the stack.
  • Before pushing a character, if the top of the stack if it's not empty, we check if the top and the current character differ by an absolute value of 32, then the two characters need to be removed as they make the string bad
  • We keep doing this until the end of string.
  • Once we traversed the entire string, the stack will hold only those characters that will make the string great.
  • We will append these strings and return the new string.

NOTE: Why 32? Because the ASCII value of a is 97 and ASCII value of A is 65. 97 - 65 = 32. Hence difference between all lowercase and uppercase alphabets will be 32.

๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿ’ป Solution - Stack

class Solution {
    public String makeGood(String s) {
        if(s == null || s.length() == 0) {
            return "";
        }
        Stack<Character> stack = new Stack<>();

        StringBuilder good = new StringBuilder();
        int n = s.length();

        for(int i = 0; i<n; i++) {
            char ch = s.charAt(i);
            if(!stack.isEmpty()) {
                char top = stack.peek();
                if(Math.abs(top - ch) == 32) {
                    stack.pop();
                    continue;
                }
            }
            stack.push(ch);
        }

        for(char ch: stack) {
            good.append(ch);
        }

        return good.toString();
    }
}
Time Complexity: O(n)
  - n = length of string
Space Complexity: O(n)
  - n = length of string
       - We use extra space for stack and to build the string.

๐Ÿ’ฌ Thought Process - Two Pointers using StringBuilder

  • Another intuitive solution is to use a two pointer sort of solution that keeps checking the current and next character.
  • If the two characters differ by 32, then we ignore these characters and try to match the next character with the previously "good character"
  • We keep repeatedly doing this until we've removed all bad characters.
  • Our good string is supposed to initially begin with the initial string.
  • Since we are using StringBuilder, we can do ad-hoc operation and change the string in-place.

image.png

๐Ÿ‘ฉ๐Ÿฝโ€๐Ÿ’ป Solution - Two Pointer using StringBuilder

class Solution {
    public String makeGood(String s) {
        if(s == null || s.length() <= 0) {
            return s;
        }

        int n = s.length();
        int i = 0;

        StringBuilder greatString = new StringBuilder(s);
        while(i < greatString.length()-1) {
            char curr = greatString.charAt(i);
            char next = greatString.charAt(i+1);

            // If the strings are not same letter but in difference cases
            if(curr - 'a' == next - 'A' || curr - 'A' == next - 'a') {
                greatString.delete(i, i+2);
                if(i > 0) i-=1;
            }
            else {
                i++;
            }

        }


        return greatString.toString();
    }
}
Time Complexity: O(N)
  N = length of string
Space Complexity: O(N)
  N = length of string
      - We will have to use additional space to delete bad characters


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!