力扣第316与1081题 不同字符的最小子序列 C++ Java Python
目录
题目
中等
相关标签
提示
给你一个字符串 s ,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证 返回结果的
字典序
最小(要求不能打乱其他字符的相对位置)。
示例 1:
输入:s = "bcabc"输出:"abc"
示例 2:
输入:s = "cbacdcbc"输出:"acdb"
提示:
- 1 <= s.length <= 104
- s由小写英文字母组成
注意:该题与 1081 . - 力扣(LeetCode) 相同
思路和解题方法
- 使用栈
stk存储结果字符串的字符,使用集合visited记录栈中已经包含的字符。- 统计每个字符出现的次数,并遍历原始字符串
s。- 对于每个字符
ch:
- 减少其出现次数。
- 如果栈中已经包含了字符
ch,则直接跳过。- 如果栈顶元素大于当前字符
ch,且后面还会出现,则将栈顶元素移除。- 将字符
ch添加到栈中,并标记为已访问。- 将栈中字符逆序输出,构成结果字符串。
复杂度:
-  时间复杂度:O(n)
- 遍历字符串的时间复杂度为 O(n),其中 n 是字符串的长度。
-  空间复杂度:O(n)
- 使用了栈和集合来存储结果字符和已访问字符,以及一个额外的数组来统计字符出现次数,因此空间复杂度为 O(n)。
c++ 代码
#include <string>
#include <stack>
#include <unordered_set>
#include <vector>
using namespace std;
class Solution {
public:
    string smallestSubsequence(string s) {
        stack<char> stk; // 用于存储结果字符串的栈
        unordered_set<char> visited; // 用于记录栈中已经包含的字符
        vector<int> count(26, 0); // 记录每个字符出现的次数
        // 统计每个字符出现的次数
        for (char ch : s) {
            count[ch - 'a']++;
        }
        for (char ch : s) {
            // 对于每个字符ch,首先减少其出现次数
            count[ch - 'a']--;
            // 如果栈中已经包含了字符ch,则直接跳过
            if (visited.count(ch)) {
                continue;
            }
            // 如果栈顶元素大于当前字符ch,且后面还会出现,则将栈顶元素移除
            while (!stk.empty() && stk.top() > ch && count[stk.top() - 'a'] > 0) {
                visited.erase(stk.top());
                stk.pop();
            }
            // 将字符ch添加到栈中,并标记为已访问
            stk.push(ch);
            visited.insert(ch);
        }
        // 将栈中字符逆序输出,构成结果字符串
        string result;
        while (!stk.empty()) {
            result = stk.top() + result;
            stk.pop();
        }
        return result;
    }
};
Java 版本(仅供参考)
import java.util.*;
class Solution {
    public String smallestSubsequence(String s) {
        Stack<Character> stk = new Stack<>(); // 用于存储结果字符串的栈
        Set<Character> visited = new HashSet<>(); // 用于记录栈中已经包含的字符
        int[] count = new int[26]; // 记录每个字符出现的次数
        // 统计每个字符出现的次数
        for (char ch : s.toCharArray()) {
            count[ch - 'a']++;
        }
        for (char ch : s.toCharArray()) {
            // 对于每个字符ch,首先减少其出现次数
            count[ch - 'a']--;
            // 如果栈中已经包含了字符ch,则直接跳过
            if (visited.contains(ch)) {
                continue;
            }
            // 如果栈顶元素大于当前字符ch,且后面还会出现,则将栈顶元素移除
            while (!stk.isEmpty() && stk.peek() > ch && count[stk.peek() - 'a'] > 0) {
                visited.remove(stk.peek());
                stk.pop();
            }
            // 将字符ch添加到栈中,并标记为已访问
            stk.push(ch);
            visited.add(ch);
        }
        // 将栈中字符逆序输出,构成结果字符串
        StringBuilder result = new StringBuilder();
        while (!stk.isEmpty()) {
            result.insert(0, stk.pop());
        }
        return result.toString();
    }
}
Python 版本(仅供参考)
class Solution:
    def smallestSubsequence(self, s: str) -> str:
        stk = []  # 用于存储结果字符串的栈
        visited = set()  # 用于记录栈中已经包含的字符
        count = [0] * 26  # 记录每个字符出现的次数
        # 统计每个字符出现的次数
        for ch in s:
            count[ord(ch) - ord('a')] += 1
        for ch in s:
            # 对于每个字符ch,首先减少其出现次数
            count[ord(ch) - ord('a')] -= 1
            # 如果栈中已经包含了字符ch,则直接跳过
            if ch in visited:
                continue
            # 如果栈顶元素大于当前字符ch,且后面还会出现,则将栈顶元素移除
            while stk and stk[-1] > ch and count[ord(stk[-1]) - ord('a')] > 0:
                visited.remove(stk[-1])
                stk.pop()
            # 将字符ch添加到栈中,并标记为已访问
            stk.append(ch)
            visited.add(ch)
        # 将栈中字符逆序输出,构成结果字符串
        return ''.join(stk)
代码细节
在 C++ 版本中,
unordered_set是用于记录栈中已经包含的字符,而vector<int> count(26, 0)是用于统计每个字符出现的次数。
C++ 中的
stk为stack<char>类型,用于存储结果字符串的字符;visited为unordered_set<char>类型,用于记录栈中已经包含的字符;count为vector<int>类型,用于记录每个字符出现的次数。
在 Java 版本中,
Stack<Character>是用于存储结果字符串的栈,Set<Character>是用于记录栈中已经包含的字符,int[] count是用于记录每个字符出现的次数。
Python 版本中使用列表
stk存储结果字符串的字符,集合visited记录栈中已经包含的字符,count为列表,用于记录每个字符出现的次数。
在遍历字符串时,对于每个字符
ch,首先减少其出现次数count[ch - 'a']--。
如果栈中已经包含了字符
ch,则直接跳过当前字符。
如果栈顶元素大于当前字符
ch,且后面还会出现,则将栈顶元素移除。
将字符
ch添加到栈中,并标记为已访问。
将栈中字符逆序输出,构成结果字符串。
觉得有用的话可以点点赞,支持一下。
如果愿意的话关注一下。会对你有更多的帮助。
每天都会不定时更新哦 >人< 。
 
                    
                     
                    
                 
                    
                 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号