Welcome to Subscribe On Youtube
1081. Smallest Subsequence of Distinct Characters
Description
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 <= 1000sconsists of lowercase English letters.
Note: This question is the same as 316: https://leetcode.com/problems/remove-duplicate-letters/
Solutions
Solution 1
Stack
Solution 2
This implementation uses breadth-first search, followed by monotonic stack, followed by bit manipulation. It traverses the relevant values and updates its state as each value is processed. The auxiliary container determines which pending state is processed next. After all required states have been considered, the maintained result is returned.
-
class Solution { public String smallestSubsequence(String text) { int[] cnt = new int[26]; for (char c : text.toCharArray()) { ++cnt[c - 'a']; } boolean[] vis = new boolean[26]; char[] cs = new char[text.length()]; int top = -1; for (char c : text.toCharArray()) { --cnt[c - 'a']; if (!vis[c - 'a']) { while (top >= 0 && c < cs[top] && cnt[cs[top] - 'a'] > 0) { vis[cs[top--] - 'a'] = false; } cs[++top] = c; vis[c - 'a'] = true; } } return String.valueOf(cs, 0, top + 1); } } // Solution 2 class Solution { public String smallestSubsequence(String s) { int n = s.length(); int[] last = new int[26]; for (int i = 0; i < n; ++i) { last[s.charAt(i) - 'a'] = i; } Deque<Character> stk = new ArrayDeque<>(); int mask = 0; for (int i = 0; i < n; ++i) { char c = s.charAt(i); if (((mask >> (c - 'a')) & 1) == 1) { continue; } while (!stk.isEmpty() && stk.peek() > c && last[stk.peek() - 'a'] > i) { mask ^= 1 << (stk.pop() - 'a'); } stk.push(c); mask |= 1 << (c - 'a'); } StringBuilder ans = new StringBuilder(); for (char c : stk) { ans.append(c); } return ans.reverse().toString(); } } -
class Solution { public: string smallestSubsequence(string s) { int n = s.size(); int last[26] = {0}; for (int i = 0; i < n; ++i) { last[s[i] - 'a'] = i; } string ans; int mask = 0; for (int i = 0; i < n; ++i) { char c = s[i]; if ((mask >> (c - 'a')) & 1) { continue; } while (!ans.empty() && ans.back() > c && last[ans.back() - 'a'] > i) { mask ^= 1 << (ans.back() - 'a'); ans.pop_back(); } ans.push_back(c); mask |= 1 << (c - 'a'); } return ans; } }; -
class Solution: def smallestSubsequence(self, s: str) -> str: last = {c: i for i, c in enumerate(s)} stk = [] vis = set() for i, c in enumerate(s): if c in vis: continue while stk and stk[-1] > c and last[stk[-1]] > i: vis.remove(stk.pop()) stk.append(c) vis.add(c) return "".join(stk) -
func smallestSubsequence(s string) string { last := make([]int, 26) for i, c := range s { last[c-'a'] = i } stk := []rune{} vis := make([]bool, 128) for i, c := range s { if vis[c] { continue } for len(stk) > 0 && stk[len(stk)-1] > c && last[stk[len(stk)-1]-'a'] > i { vis[stk[len(stk)-1]] = false stk = stk[:len(stk)-1] } stk = append(stk, c) vis[c] = true } return string(stk) } -
function smallestSubsequence(s: string): string { const f = (c: string): number => c.charCodeAt(0) - 'a'.charCodeAt(0); const last: number[] = new Array(26).fill(0); for (const [i, c] of [...s].entries()) { last[f(c)] = i; } const stk: string[] = []; let mask = 0; for (const [i, c] of [...s].entries()) { const x = f(c); if ((mask >> x) & 1) { continue; } while (stk.length && stk[stk.length - 1] > c && last[f(stk[stk.length - 1])] > i) { mask ^= 1 << f(stk.pop()!); } stk.push(c); mask |= 1 << x; } return stk.join(''); }