leetcode:316. Remove Duplicate Letters 题解

题目

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”

理解题目:
输入一个字符串,字母来自a-z,然后去除里面重复的字符,使得每个字母只能保留一个,且最后的字符串又是字母序最小的。

地址

https://leetcode.com/problems/remove-duplicate-letters/description/

解题思路

用最原始的分析思路,用例子的bcabc来说明。

  1. 依次扫描字符。
  2. 发现是b,放到结果里。 > b
  3. 发现是c,回头看看已有的b,虽然后面也有b,但是b很小,没必要用后面的。 >bc
  4. 继续扫描a,发现前面的bc都比a大,而且后面还有bc,那么bc清理掉。放入a。简单理解则是:后面有更优的(字母序小) >a
  5. 继续扫描b,发现里面还没放入,而且前面的都小;>ab
  6. 继续扫描c,发现没有,而且前面的都是小的,直接放入; >abc
  7. 结束。

由上面的分析设计一个算法:

1. 扫描字符串,结果串置空;
2. 如果当前字符用过了,扫描下一个;
3. 如果当前字符串没用过,则判定结果串的字符串是否存在需要优化的字符。优化的条件:里面有大于当前字符的,并且后面存在重复的,也就是用后面的即可。
4. 重复2,3步骤直到无字符串可以扫描。
5. 按先进先出的原则输出结果串。

要实现上述算法需要一些技巧,参考代码。

代码

 public String removeDuplicateLetters(String s) {

         //统计每个字符出现的次数
         int [] count = new int[26];
         char cs [] = s.toCharArray();
         for(char c: cs)
         {
             count[c-'a']++;
         }

         //每个字符是否使用,由于只保留一个,所以这地方最多需要26个。
         boolean visited [] = new boolean[26];

         //结果集
         Stack<Character> result = new Stack<Character>();
         for(char c: cs)
         {
             count[c-'a']--;
            //结果集里已经有了,不需要再放进来了。
             if(visited[c-'a'])
                 continue;

             //优化步骤
             while(!result.isEmpty() && count[result.peek()-'a']>0 && c<result.peek())
             {
                //后面有更好的,则删除,设置为没有用过。
                visited[result.peek()-'a']=false;
                result.pop();
             }

             //更新状态
             result.push(c);
             visited[c-'a'] = true;
         }
         s = "";
         //正序,先入的先出!
        for(char c: result)
            s+=c;

            return s;
        }

总结

  1. stack的运用, 后进先出:last in first out。
  2. 思路很重要,优化策略。类似迭代公式。

参考

https://en.wikipedia.org/wiki/Stack_(abstract_data_type)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值