Leetcode之Remove Duplicate Letters

来源:互联网 发布:阿里云网站备案拍照 编辑:程序博客网 时间:2024/05/29 14:22

题目描述如下:

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

Example:

Given "bcabc"
Return "abc"

Given "cbacdcbc"
Return "acdb"

这道题让我们移除重复字母,使得每个字符只能出现一次,而且结果要按字母顺序排,前提是不能打乱其原本的相对位置。

分析

方法一

这道题可以采用Greedy的思想,因为最后想要的结果是最小值,所以我们在满足要求的情况下不断append最小的字符, 最后便可得到最小的字符串.我们可以用一个数组记录每个字符出现的次数,用一个指针从左到右扫找当前最小字符,过程中减少对应字符次数, 找的过程中终止条件是发现某个字符次数等于0,因为继续扫的话最终结果很有可能缺那个字符.

java代码:

public class Solution {    public String removeDuplicateLetters(String s) {        if (s == null ||s.length() == 0)            return s;                    // 记录每个字符出现的次数            int[] cnt = new int[26];        for (int i = 0; i < s.length(); i++) {            cnt[s.charAt(i) - 'a']++;        }                // 找出当前最小字符        int pos = 0;        for (int i = 0; i < s.length(); i++) {            if (s.charAt(i) < s.charAt(pos))                pos = i;                        // 避免无字符可用            if (--cnt[s.charAt(i) - 'a'] == 0)                break;        }                // 除去字符串中已经append的字符的所有重复值        return s.charAt(pos) + removeDuplicateLetters(s.substring(pos + 1).replaceAll("" + s.charAt(pos), ""));    }}

方法二

其实跟上个方法差不多,但是可以优化下,用stack的话,最多每个字符过两遍就可以了。读字符的过程中,把字符存到stack里,当发现stack之前存的字符中比当前字符大而且频率还大于0就可以把那个字符pop出去。类似这种题目都可以用stack解决。基本思想就是在一定的限制条件下pop出比当前选择差的元素

java代码:

public class Solution {    public String removeDuplicateLetters(String s) {        int[] freqs = new int[26];                // 统计字符频率        for (int i = 0; i < s.length(); i++) {            freqs[s.charAt(i)]++;        }        boolean[] visited = new boolean[26]; // 用来标记存在stack里的字符        Deque<Character> q = new ArrayDeque<>();                    for (int i = 0; i < s.length(); i++) {            char c = s.charAt(i);            freqs[c]--;            if (visited[c]) continue;            // pop出stack当中比当前字符大但后面还存在的的字符,            while (!q.isEmpty() && q.peek() > c && freqs[q.peek()] > 0) {                visited[q.pop()] = false;            }            q.push(c);            visited[c] = true;        }        StringBuilder sb = new StringBuilder();        for (char c : q) {            sb.append(c);        }        return sb.reverse().toString();    }}

Python代码:
class Solution(object):    def removeDuplicateLetters(self, s):        """        :type s: str        :rtype: str        """        if s == None or len(s) <= 1:            return s                visit = [0] * 26        count = [0] * 26        length = len(s)                for i in range(length):            count[ord(s[i]) - 97] += 1                result = ""                for i in range(length):            c = s[i]            index = ord(c) - 97            count[index] -= 1            if visit[index] == 1:                continue            while len(result) != 0 and result[-1] > c and count[ord(result[-1]) - 97] > 0:                visit[ord(result[-1]) - 97] = 0                result = result[:len(result) - 1]            result = result + s[i]            visit[index] = 1                return result



0 0
原创粉丝点击