Lexicographically Minimum String After Removing Stars - Complete Solution Guide
Lexicographically Minimum String After Removing Stars is LeetCode problem 3170, a Medium level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.
Problem Statement
You are given a string s . It may contain any number of '*' characters. Your task is to remove all '*' characters. While there is a '*' , do the following operation: Delete the leftmost '*' and the smallest non- '*' character to its left . If there are several smallest characters, you can delete any of them. Return the lexicographically smallest resulting string after removing all '*' characters. Example 1: Input: s = "aaba*" Output: "aab" Explanation: We should delete one of the 'a' characters
Detailed Explanation
The problem requires you to process a string `s` containing lowercase English letters and asterisks ('*'). The goal is to remove all '*' characters following a specific rule: for each '*' encountered, you must also remove the leftmost smallest non-'*' character to its left. The 'smallest' character refers to its lexicographical order (a < b < c, etc.). The final result should be the lexicographically smallest string after all '*' characters have been processed and removed.
Solution Approach
The solution uses a greedy approach. It iterates through the string, and for each character: If it's a '*', it searches for the leftmost smallest non-'*' character that hasn't been removed yet and removes it, along with the '*'. If it's a regular character, it stores its index for later removal if a '*' is encountered. A boolean array keeps track of removed characters to avoid repeated string modifications. The indexes of each character is saved in a list of stacks, where index of stack represents the ascii index of the char.
Step-by-Step Algorithm
- Step 1: Initialize a list of stacks, 'positions', where each stack at index 'i' stores the indices of the character 'a' + i in the original string. Also, initialize a boolean array 'is_removed' to track characters that have been removed.
- Step 2: Iterate through the string 's'.
- Step 3: If the current character is '*', mark it as removed (is_removed[i] = true). Iterate through the positions list in the range 0-25. If stack at index j is not empty, pop the top element from this stack (which will be the last occurence of this character to the left of '*'). Mark this characters position as removed using is_removed[idx_to_remove] = true, and break out of the inner loop.
- Step 4: If the current character is not a '*', calculate its index (char - 'a') and push the current index i to the corresponding stack in the positions array.
- Step 5: Create the final result string by iterating through the original string and appending characters that are not marked as removed in the is_removed array.
- Step 6: Return the resulting string.
Key Insights
- Insight 1: The order of processing '*' characters matters since removing characters earlier affects what's available for later removals.
- Insight 2: We can greedily remove the leftmost smallest available character for each '*'. This is key for obtaining the lexicographically smallest final string.
- Insight 3: Maintaining the positions of characters and a separate flag array for removed characters avoids repeated string manipulations, which are costly.
Complexity Analysis
Time Complexity: O(n)
Space Complexity: O(n)
Topics
This problem involves: Hash Table, String, Stack, Greedy, Heap (Priority Queue).
Companies
Asked at: Flexera.