Smallest Subsequence of Distinct Characters - Complete Solution Guide
Smallest Subsequence of Distinct Characters is LeetCode problem 1081, 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
Given a string s , return the lexicographically smallest subsequence of s that contains all the distinct characters of s exactly once . Example 1: Input: s = "bcabc" Output: "abc" Example 2: Input: s = "cbacdcbc" Output: "acdb" Constraints: 1 <= s.length <= 1000 s consists of lowercase English letters. Note: This question is the same as 316: https://leetcode.com/problems/remove-duplicate-letters/
Detailed Explanation
The problem asks us to find the lexicographically smallest subsequence of a given string `s` that contains all distinct characters of `s` exactly once. A subsequence is a sequence that can be derived from another sequence by deleting some or no elements without changing the order of the remaining elements. Lexicographically smallest means that among all possible subsequences satisfying the condition, we want the one that comes first in dictionary order. For example, 'abc' is lexicographically smaller than 'acb'. The input is a string `s` consisting of lowercase English letters, and the output is the smallest subsequence.
Solution Approach
The solution uses a greedy approach with a stack. We iterate through the input string `s`. For each character, we check if it's already present in our stack (meaning it's already in our potential subsequence). If not, we compare the current character with the top of the stack. If the current character is lexicographically smaller than the top of the stack, AND the character at the top of the stack occurs later in the string, we can pop the top of the stack. We repeat this popping process until either the stack is empty or the conditions are no longer met. Then, we push the current character onto the stack and mark it as 'seen'. Finally, the stack contains the characters of the smallest subsequence in the correct order, which we then convert to a string.
Step-by-Step Algorithm
- Step 1: Initialize a hash map `last_occurrence` to store the last index of each character in the string `s`. This is done in a single pass through the string.
- Step 2: Initialize an empty stack `stack` to store the characters of the potential smallest subsequence.
- Step 3: Initialize an empty set `seen` to keep track of which characters are already in the stack.
- Step 4: Iterate through the string `s` from left to right.
- Step 5: For each character `char` at index `i`, check if `char` is already in the `seen` set. If so, skip to the next character.
- Step 6: While the stack is not empty, the current character `char` is less than the character at the top of the stack, and the last occurrence of the character at the top of the stack is greater than the current index `i`, pop the character from the stack and remove it from the `seen` set.
- Step 7: Push the current character `char` onto the stack and add it to the `seen` set.
- Step 8: After iterating through the entire string, convert the stack to a string and return it.
Key Insights
- Insight 1: The problem can be solved using a monotonic stack. The stack helps to maintain the potential smallest subsequence while iterating through the string.
- Insight 2: The `last_occurrence` map is crucial. It allows us to determine if a character currently in the stack can be removed because it appears later in the string.
- Insight 3: The `seen` set is used to ensure each distinct character appears only once in the result.
Complexity Analysis
Time Complexity: O(n)
Space Complexity: O(1)
Topics
This problem involves: String, Stack, Greedy, Monotonic Stack.
Companies
Asked at: ByteDance, FactSet.