Leedcode 316. 去除重复字母

题目

去除重复字母

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

在这里插入图片描述

题目分析

这个问题一共有2部分,第一个是去除重复的元素,第二个是字典序最小。

对于第一个问题很好理解,就是输入的字符串包含重复的字符,需要我们去重,没啥好说的。

第二个问题:为什么会存在字典序最小这个问题?因为给定的字符串中的英文字母是乱序的,没有保持从小到大的顺序,(即:a < b < c < d < ... < z)。如果是保持从小到大的顺序,不管怎么重复,都很好解决。例如aabbbbcccdddzzzz 让你删除重复的元素并保持字典序最小,就非常简单了。

因此我们知道了输入字符串的乱序是造成字典序最小这个问题的原因之一。

此外单个字符串的字典序是确定的,没有所谓的大小。但是如果要求我们把重复的字符删掉,同时保证其余的字符顺序保持不变。这样子原来输入的字符串就能够演变成多个字符串,因此多个乱序字符串之间就可以比较字典序大小了。

综上,乱序去重是导致字典序最小问题的原因。

因此如果要使得字典序最小,就要关注造成乱序的那个字符。举个例子,对于cbacdcbc

  1. 第一个字符是c

  2. 第二个字符是bbc小,形成了乱序,那么如果我们能够把b前面的c删掉,这个乱序就消失了。
    2.1. 那么问题来了:能不能删呢?答案是可以的,因为题目本来就让我们去重,而想要删掉的b,在这个字符串后面还出现了2次,那当然可以删除。

  3. 第三个字符是aab小,又形成了乱序,同样的道理,如果我们能把b删掉,就解决了这个乱序。能不能删?可以!因为后面还有一个b, cbacdcbc。

  4. 经过上面的操作,已经暂时确定字符是acb都被我们删了

  5. 第四个字符是c,满足字典序,暂时确定的字符是ac

  6. 第五个字符是d,满足字典序,暂时确定的字符就是acd

  7. 第六个字符是c,注意:这个字符在我们暂时确定的字符acd中已经出现了,但是题目要求我们只能保留一个,我们究竟是删除前面的字符c,还是删除我们现在遍历到的字符c?,答案很明显,应该删除现在遍历到字符c,因为我们暂时确定的字符acd是满足字典序的,如果删除前面一个c,保留遍历到的c,就变成了adc,显然,字典序变大了。
    7.1. 值得注意的是,如果第六个字符是d,其实情况有点不同:已经暂时确定的字符是acd,现在遇到了d,这个时候删除哪个d都是一样的。所以为了统一,统一理解为删除当前遍历到的字符

  8. 第7个字符是b,已经确定的字符是acd,同样不满足字典序了,但是能将d字符删掉么?答案是不不能的,因为题目要求每个字符必须保留一个,后面已经没有d了,怎么能删呢?所以虽然这里不满足字典序但是不能删除,因此已经确定的字符是acdb

  9. 第8个字符是c,这个字符在已经确定的字符acdb中已经出现过了,按照上面的说法,应该删除掉当前遍历到的字符。
    10.所以最后的结果就是acdb

代码流程

经过上面的例子分析,我们总结得到如下的处理过程:

  • 情况1:遍历这个字符串,如果遇到了满足字典序的情况,例如abcd,就直接按照顺序存下来
  • 如果遇到了不满足字典序的情况:例如abcd后面一个是c。这个时候得处理乱序,就得分情况考虑,为了方便起见,我们将与遍历到的字符形成乱序的字符,叫做关键字符,就是上例的d
    • 情况2:如果新遇到的字符在已经暂时确定的字符串中出现过,处理乱序的做法是:删除的是当前遍历到的字符,但具体做法是跳过这个字符,不将他添加到结果序列中,等价于删除了
    • 情况3:如果新遇到的字符没有在暂时确定的字符串中出现过,并且关键字符在后面不再出现了,这是处理乱序的做法是:接受这个乱序,将遍历到的字符保存下来,因为不能删除元素
    • 情况4:如果新遇到的字符没有在暂时确定的字符串中出现过,并且关键字符在后面还会出现,这时候就可以将关键字符删掉
  • 以上一共4种情况,前3种都可以遍历下一个元素,但是最后一种情况不行,因为他将关键字符删除了,需要继续判断当前遍历的元素与新的关键字符的关系,重复上述过程。举个例子adf遇到了c,假设后面还有df,因此根据上述说法,f将会被删掉,但是c还是与新的关键字符形成了乱序,又得循环判断一次。

因此,我们可以将暂时确定的字符保存在栈中,关键字符的删除,等价于栈的弹出,然后新的栈顶元素充当关键字符。我们需要判断某个字符在后序还会不会出现,因此需要实时记录遍历到当前位置,后面字符剩余个数的情况,可以用一个int[] nums数组来记录。还需要判断当前遍历到的字符,有没有在暂时确定的字符中出现过,即有没有在栈中出现,因此需要一个boolen[] isInStack数组来记录存在情况。

代码实现

public class Solution01 {
   

    public String removeDuplicateLetters
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值