返回介绍

solution / 1000-1099 / 1081.Smallest Subsequence of Distinct Characters / README

发布于 2024-06-17 01:03:31 字数 5251 浏览 0 评论 0 收藏 0

1081. 不同字符的最小子序列

English Version

题目描述

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

 

示例 1:

输入:s = "bcabc"
输出"abc"

示例 2:

输入:s = "cbacdcbc"
输出:"acdb"

 

提示:

  • 1 <= s.length <= 1000
  • s 由小写英文字母组成

 

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

解法

方法一:栈

我们用一个数组 $last$ 记录字符串 $s$ 每个字符最后一次出现的位置,用栈来保存结果字符串,用一个数组 $vis$ 或者一个整型变量 $mask$ 记录当前字符是否在栈中。

遍历字符串 $s$,对于每个字符 $c$,如果 $c$ 不在栈中,我们就需要判断栈顶元素是否大于 $c$,如果大于 $c$,且栈顶元素在后面还会出现,我们就将栈顶元素弹出,将 $c$ 压入栈中。

最后将栈中元素拼接成字符串作为结果返回。

时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是字符串 $s$ 的长度。

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)
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);
  }
}
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;
  }
};
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('');
}

方法二

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();
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文