Leetcode 316 Remove Duplicate Letters

Leetcode 316 Remove Duplicate Letters

题目

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

Note: This question is the same as 1081: https://leetcode.com/problems/smallest-subsequence-of-distinct-characters/

Example 1:
Input: s = “bcabc”
Output: “abc”

Example 2:
Input: s = “cbacdcbc”
Output: “acdb”

Constraints:
1 <= s.length <= 104
s consists of lowercase English letters.

代码

这题是完全没想出来,直接参考了Leetcode得Sample答案,重点在于使用Stack的结构。因为想要按照字典序排序,那我们知道我们希望留下的那些字母的位置是后面的字母比他大的时候。先看代码如下

class Solution {
    public String removeDuplicateLetters(String s) {
        if (s == null || s.length() == 0) {
            return s;
        }
        
        int[] f = new int[26];
        for (char c : s.toCharArray()) {
            f[c - 'a']++;
        }
        
        Stack<Character> stack = new Stack<>();
        boolean[] visited = new boolean[26];
        
        for (char c : s.toCharArray()) {
            int idx = c - 'a';
            f[idx]--;
            if (visited[idx]) {
                continue;
            }
            
            while (!stack.isEmpty() && c < stack.peek() && f[stack.peek() - 'a'] != 0) {
                visited[stack.pop() - 'a'] = false;
            }
            stack.push(c);
            visited[idx] = true;
        }
        
        StringBuilder sb = new StringBuilder();
        while (!stack.isEmpty()) {
            sb.insert(0, stack.pop());
        },
        return sb.toString();
    }
}

根据代码来过两个例子。

s = “bcabc”

  • char ‘b’,此时stack为空直接加入
  • char ‘c’,此时比b大直接加入
  • char ‘a’,此时比c小了,那我们是希望如果后面还有c的话就不要这个c了,所以会判断f[stack.peek() - 'a'] != 0,此时pop('c'),对b也做了一样的判断,也有a < b所以pop('b'),这时stack空加入a
  • 最后加入b和c

对比若s = “bcab”
到第三步的时候,虽然在a前面的b比他大,但是因为中间有一个c并且只有这一个了,那么并不会做任何操作。
可以看到"bca"确实是小于"cab"的,因为b<c依然是满足的,所以一直都只需要判断相邻的两个字母即可

若s = “bcac”,那答案就会是"bac"。

通过以上的例子我们可以理解该算法的大意是不断找到比前面字符大的位置加入,除非前面的字符只有一个或是本身就比它大,这是一种贪心算法,通过比较是将stack中的字符pop出后面再次加入,还是保持原位,可以知道pop为最优答案。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值