LeetCode #316 Remove Duplicate Letters

题目

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 1:

Input: "bcabc"
Output: "abc"

Example 2:

Input: "cbacdcbc"
Output: "acdb"

Difficulty: Hard

分析

题目的关键是,要给出词典顺序最小的结果字符串。

我一开始的想法是,从后往前检查,把搜到的第一个不唯一的字符 s[i] ,和它前面的一个副本 s[j] ,比较 s[j..i-1]s[j+1...i] ,从而决定要选择哪个位置,去除哪个字符。

比如:

bcabc -> (remove b) -> babc  -> (remove b) -> abc
cbacdcbc -> (remove c) -> cbacdbc -> (remove c) -> cbacdb -> (remove b) -> cacdb -> (remove c) -> acdb

但是有一个反例:

defcbeabdc -> (remove c) -> defbeabdc -> (remove d) -> defbeabc 
	-> (remove b) -> defbeac -> (remove e) -> defbac

正确答案应为 defabc

贪心算法

在网站上我看到了这个递归的贪心算法,它的思路是这样的。

思路

每一次的贪心选择即为答案最左端的字母。如何进行贪心选择呢?由题目要求可以知道,这个贪心选择得到的字母应该尽可能地小。姑且称呼这个选择为“最小字母”,它应当是在一定范围内最小的字母。

但是,这样的贪心选择必然有中止条件或限制范围。假想某个“最小字母”左边有唯一的字母,比如CBDDF,B左边有C,C在该字符串中是唯一的。这种情况下,以B作为贪心选择是不合理的。

而如果“最小字母”左边的字母,在“最小字母”右边也有它们的重复,那么左边的这些字母完全可以舍去,它们不会比“最小字母”小,由它们无法得到字典顺序最小的答案字符串。比如CBABC,A左边的CB可以舍去。

所以,字符串 s 中的 “最小字母” s[pos] 应该满足这样的条件:

  • s[0...pos-1] 中的字母,在字符串 s 中不是唯一的

  • s[pos...] 中的字母包括了所有在字符串 s 中唯一的字母

(在字符串 s 中没有唯一字母的情况下,会有多个“最小字母”,比如abcacb。这时选择最左边的“最小字母”。)

取出 s[pos] ,加入答案字符串中。把右边的子串 s[pos+1...] 中重复的字母 s[pos] 去掉后,对新的字符串重复上述操作。

例子

答案字符串 待处理字符串 第一个唯一字母 最小字母
defcbeabdc f d
d efcbeabc f e
de fcbabc f f
def cbabc a a
defa bc
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值