返回 s 字典序最小的子序列,该子序列包含 s 的所有不同字符,且只包含一次。

    注意:该题与 316 https://leetcode.com/problems/remove-duplicate-letters/ 相同

    示例 1:

    输入:s = “bcabc”
    输出:”abc”
    示例 2:

    输入:s = “cbacdcbc”
    输出:”acdb”

    1. /**
    2. * @param {string} s
    3. * @return {string}
    4. */
    5. var smallestSubsequence = function (s) {
    6. // 存放去重的结果
    7. let stack = [];
    8. // 维护一个计数器记录字符串中字符的数量
    9. // 因为输入为 ASCII 字符,大小 256 够用了
    10. let count = new Array(256).fill(0);
    11. for (let i = 0; i < s.length; i++) {
    12. count[s.charCodeAt(i)]++;
    13. }
    14. let inStack = [];
    15. for (let c of s) {
    16. // 每遍历过一个字符,都将对应的计数减一
    17. count[c.charCodeAt(0)]--;
    18. // 如果字符 c 存在栈中,直接跳过
    19. if (inStack[c]) continue;
    20. // 插入之前,和之前的元素比较一下大小
    21. // 如果字典序比前面的小,pop 前面的元素
    22. while (
    23. stack.length &&
    24. stack[stack.length - 1].charCodeAt(0) > c.charCodeAt(0)
    25. ) {
    26. // 若之后不存在栈顶元素了,则停止 pop
    27. if (count[stack[stack.length - 1].charCodeAt(0)] == 0) {
    28. break;
    29. }
    30. // 若之后还有,则可以 pop
    31. // 弹出栈顶元素,并把该元素标记为不在栈中
    32. inStack[stack.pop()] = false;
    33. }
    34. // 若不存在,则插入栈顶并标记为存在
    35. stack.push(c);
    36. inStack[c] = true;
    37. }
    38. return stack.join("");
    39. };

    image.png