LeetCode 每日一题316. 去除重复字母

316. 去除重复字母

给你一个字符串 s ,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证 返回结果的字典序最小(要求不能打乱其他字符的相对位置)。

示例 1:

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

示例 2:

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

提示:

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

解题思路:

知道要利用「单调栈」的思想,但是没做出来~,最后参考官方思路写的。

维护一个栈,存放结果字母。从左往右遍历字符串,当有新字母加入时:

  1. 判断栈顶字母是否大于新字母,若大于,应该踢出栈顶元素加入新元素
  2. 重复步骤 1
  3. 步骤 1 边界条件:栈里有元素 && 栈顶元素大于新元素 && 后面还有栈顶元素

方法一:单调栈

public String removeDuplicateLetters(String s) {
    // 小写字母26个,表示字母是否已经加入栈
    boolean[] visited = new boolean[26];
    // 每个字母出现次数
    char[] counts = new char[26];
    for (int i = 0; i < s.length(); i++) {
        counts[s.charAt(i) - 'a']++;
    }

    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < s.length(); i++) {
        char ch = s.charAt(i);
        if (!visited[ch - 'a']) {
            // 栈里有元素 && 栈顶元素大于新元素 && 后面还有栈顶元素
            while (sb.length() > 0 && sb.charAt(sb.length() - 1) > ch && counts[sb.charAt(sb.length() - 1) - 'a'] > 0) {
                visited[sb.charAt(sb.length() - 1) - 'a'] = false;
                sb.deleteCharAt(sb.length() - 1);
            }
            visited[ch - 'a'] = true;
            sb.append(ch);
        }
        counts[ch - 'a']--;
    }
    return sb.toString();
}

执行结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值