Remove Duplicate Letters

medium string stack greedy monotonic stack

Problem

Given a string s, remove duplicate letters so that every letter appears once and only once. Return the result that is the smallest in lexicographical order among all possible results.

Inputs = "cbacdcbc"
Output"acdb"

def remove_duplicate_letters(s):
    last = {c: i for i, c in enumerate(s)}
    stack, in_stack = [], set()
    for i, c in enumerate(s):
        if c in in_stack: continue
        while stack and c < stack[-1] and last[stack[-1]] > i:
            in_stack.discard(stack.pop())
        stack.append(c); in_stack.add(c)
    return "".join(stack)
function removeDuplicateLetters(s) {
  const last = {};
  for (let i = 0; i < s.length; i++) last[s[i]] = i;
  const stack = [], inStack = new Set();
  for (let i = 0; i < s.length; i++) {
    const c = s[i];
    if (inStack.has(c)) continue;
    while (stack.length && c < stack[stack.length - 1] && last[stack[stack.length - 1]] > i) {
      inStack.delete(stack.pop());
    }
    stack.push(c); inStack.add(c);
  }
  return stack.join("");
}
class Solution {
    public String removeDuplicateLetters(String s) {
        int[] last = new int[26];
        for (int i = 0; i < s.length(); i++) last[s.charAt(i) - 'a'] = i;
        boolean[] in = new boolean[26];
        Deque<Character> stack = new ArrayDeque<>();
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (in[c - 'a']) continue;
            while (!stack.isEmpty() && c < stack.peek() && last[stack.peek() - 'a'] > i) {
                in[stack.pop() - 'a'] = false;
            }
            stack.push(c); in[c - 'a'] = true;
        }
        StringBuilder sb = new StringBuilder();
        while (!stack.isEmpty()) sb.append(stack.pollLast());
        return sb.toString();
    }
}
string removeDuplicateLetters(string s) {
    int last[26] = {0};
    for (int i = 0; i < (int)s.size(); i++) last[s[i] - 'a'] = i;
    bool inStack[26] = {false};
    string stk;
    for (int i = 0; i < (int)s.size(); i++) {
        char c = s[i];
        if (inStack[c - 'a']) continue;
        while (!stk.empty() && c < stk.back() && last[stk.back() - 'a'] > i) {
            inStack[stk.back() - 'a'] = false;
            stk.pop_back();
        }
        stk.push_back(c); inStack[c - 'a'] = true;
    }
    return stk;
}
Time: O(n) Space: O(1) (26 letters)