https://leetcode.com/problems/remove-duplicate-letters/
参考
http://www.hrwhisper.me/leetcode-remove-duplicate-letters/
https://leetcode.com/discuss/73777/easy-to-understand-iterative-java-solution
http://www.bubuko.com/infodetail-1249912.html
http://bookshadow.com/weblog/2015/12/09/leetcode-remove-duplicate-letters/
总体思路:找每个字符出现的最后的位置last_pos,然后按照key = last_pos进行排序。从第一个区间里找到最小的字母,其对应的index为k,这个时候我们remove掉这个最小字母在OrderDict里的元素,然后将start = k + 1, 然后从k+1开始搜索,end始终为OrderDict的第一个元素,一直到OrderDict为空。
找每个字符出现的最后的位置, 取其中最小的作为end。求得end对应的字母X之后,其余字母以及X,要不就在end之前重复,要不就不重复,其对应的index是唯一的index。
这里注意求last_pos的trick
last_pos = collections.defaultdict(int)
for i, c in enumerate(s):
last_pos[c] = i
自己重写code
未用orderdict,用tuple list。注意上面的思路
class Solution(object):
def removeDuplicateLetters(self, s):
"""
:type s: str
:rtype: str
"""
if len(s) == 0: return ''
idx_dict = {}
for i in xrange(len(s)):
idx_dict[s[i]] = i
alist = []
for k,v in idx_dict.items():
alist.append((k,v))#用tuple list,记录(letter, last_index)
alist.sort(key = lambda x : x[1])
start,i = 0,0
ans = ''
while i < len(s):
if len(alist) > 0:
(letter,idx) = alist[0]
min_letter = 'z'
while i <= idx:
if s[i] < min_letter and (s[i], idx_dict[s[i]]) in alist:#这里要s[i]在alist里面
min_letter = s[i]
start = i + 1
i += 1
i = start#再从start这里开始搜,搜到alist第一个元素的idx
ans += min_letter
alist.remove((min_letter, idx_dict[min_letter]))
else:
break
return ans
按照ref里的,用orderdict实现如下
class Solution(object):
def removeDuplicateLetters(self, s):
"""
:type s: str
:rtype: str
"""
if len(s) == 0: return ''
idx_dict = {}
for i in xrange(len(s)):
idx_dict[s[i]] = i
idx_dict = collections.OrderedDict(sorted(idx_dict.items(), key = lambda x:x[1]))#这里不要忘记.items()
start, i = 0, 0
ans = ''
while i < len(s):
if len(idx_dict) > 0:
end = idx_dict.items()[0][1]#注意不是idx_dict.items[0][1], 要加括号
min_letter = 'z'
while i <= end:#注意这里不要少了等号
if s[i] < min_letter and s[i] in idx_dict:
min_letter = s[i]
start = i + 1
i += 1
i = start#下一次从这个start开始
ans += min_letter
del idx_dict[min_letter]
else:
break
return ans