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.When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force approach to finding the smallest subsequence with distinct characters means we're going to try every single possibility. We'll generate every possible subsequence, check if it meets our criteria (being distinct), and keep track of the best one we've found so far.
Here's how the algorithm would work step-by-step:
def smallest_subsequence_distinct_brute_force(input_string):
shortest_unique_subsequence = ""
# Generate all possible subsequences.
for i in range(1 << len(input_string)):
subsequence = ""
for j in range(len(input_string)):
if (i >> j) & 1:
subsequence += input_string[j]
# Check if the subsequence contains distinct characters.
if len(set(subsequence)) == len(subsequence):
#Ensure only distinct characters are taken into account
if shortest_unique_subsequence == "" or len(subsequence) < len(shortest_unique_subsequence):
# Update the shortest subsequence.
shortest_unique_subsequence = subsequence
return shortest_unique_subsequence
To find the smallest subsequence with unique characters, we use a clever way to build the subsequence one character at a time, ensuring we pick the right characters in the right order. This approach avoids exploring all possible subsequences by making smart choices based on the input string's remaining characters.
Here's how the algorithm would work step-by-step:
def smallestSubsequence(input_string):
letter_counts = {}
for letter in input_string:
letter_counts[letter] = letter_counts.get(letter, 0) + 1
stack_of_letters = []
seen_letters = set()
for letter in input_string:
letter_counts[letter] -= 1
if letter in seen_letters:
continue
# This ensures the smallest lexicographical order
while stack_of_letters and letter < stack_of_letters[-1] and letter_counts[stack_of_letters[-1]] > 0:
seen_letters.remove(stack_of_letters[-1])
stack_of_letters.pop()
# Keep track of what's in our potential result
stack_of_letters.append(letter)
seen_letters.add(letter)
return ''.join(stack_of_letters)
Case | How to Handle |
---|---|
Empty input string | Return an empty string, as there are no characters to include in the subsequence. |
Null input string | Treat as empty string or throw IllegalArgumentException, depending on requirements. |
Input string with only one distinct character | Return the input string itself, as it already satisfies the conditions. |
Input string with all the same characters (e.g., 'aaaa') | Return the single character, as only one instance is needed. |
Input string with characters in reverse lexicographical order (e.g., 'zyx') | The solution should correctly identify and maintain the correct order, so the result should be 'xyz'. |
Input string with characters already in lexicographical order (e.g., 'abc') | Return the input string, as it already satisfies the lexicographical order. |
Very long input string (performance considerations) | The solution must have linear time complexity in relation to the length of the input string, making sure that operations such as substring searches and sorting can be executed efficiently. |
Input string with all lowercase letters of the alphabet included | The algorithm correctly handles all distinct characters without omission; the output should include all 26 characters in the correct order. |