力扣第316题“去除重复字母”的解题思路

参考代码:

class Solution {
    public String removeDuplicateLetters(String s) {
        Stack<Character> stack = new Stack<>();
        //数组seen记录当前栈中已经存在的字符,如果后续再遇到可以直接跳过
        boolean[] seen = new boolean[26];
        //last_occurrence 记录字符串中出现过的字符在字符串最后⼀次出现的位置
        int[] last_occurrence = new int[26];
        for (int i = 0; i < s.length(); i++)
            last_occurrence[s.charAt(i) - 'a'] = i;
        //从左到右扫描字符串
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            //若当前字符已经在栈中,⽆需处理
            if (!seen[c - 'a']) {
                while (!stack.isEmpty() && c < stack.peek() && last_occurrence[stack.peek() - 'a'] > i)
                    seen[stack.pop() - 'a'] = false;
                seen[c - 'a'] = true;
                stack.push(c);
            }
        }
        String result = "";
        while (!stack.isEmpty())
            result = stack.pop() + result; //将栈中的字⺟连接起来
        return result;
    }
}

大致思路:出现新字符,就放入栈中,如果出现的新字符小于栈顶的元素就抛弃栈顶的元素。

具体实现:

1.创建数组seen记录当前栈中已经存在的字符,如果后续再遇到可以直接跳过,具体作用在后面会讲到,这里需要知道Boolean数组默认为false

2.创建数组last_occurrence 记录字符串中出现过的字符在字符串最后⼀次出现的位置

3.for (int i = 0; i < s.length(); i++)
            last_occurrence[s.charAt(i) - 'a'] = i;

通过for循环记录字符串中出现过的字符在字符串最后⼀次出现的位置

4.if (!seen[c - 'a']) {
                while (!stack.isEmpty() && c < stack.peek() && last_occurrence[stack.peek() - 'a'] > i)
                    seen[stack.pop() - 'a'] = false;

当栈不为空,并且当当前字符小于栈顶元素时,并且当栈顶元素在后面还会出现时(因为只出现一次我们不能抛弃这个栈顶),需要将seen数组中栈顶元素对应的改为false,这样在下次出现时可以进入if语句

5.seen[c - 'a'] = true;
                stack.push(c);

将所有已经进栈的字符做标记,下次可以直接跳过if语句,对下一个字符进行判断。

扫描二维码关注公众号,回复: 15481908 查看本文章

6.String result = "";
        while (!stack.isEmpty())
            result = stack.pop() + result; //将栈中的字⺟连接起来
        return result;

最后将所有栈中的字母连接起来。

对于第一个字符,seen默认值为false,进入if语句中,因为栈为空,所以不进入while循环,标记该字符,令seen[]=true,方便下次再次出现直接跳过,最后让该字符入栈,后续循环就是依照第四步进行判断。

猜你喜欢

转载自blog.csdn.net/weixin_63994459/article/details/123723987