Suppose we have a text, we have to find the lexicographically smallest subsequence of text that contains all the distinct characters of text exactly once. So if the input is like “cdadabcc”, then the output will be “adbc”.
To solve this, we will follow these steps −
- Define a stack st, two maps last_o and considered, they are initially blank
- for i in range length of text – 1 down to 0
- if text[i] is not present in last_o −
- last_o[text[i]] := i
- considered[text[i]] := false
- i := 0
- while i < length of text
- if stack has no elements
- push text[i] into stack
- considered[text[i]] := true
- increase i by 1
- otherwise stack top > text[i] and considered[text[i]] is false
- if last_o[stack top] > i
- considered[stack top element] := false
- pop from stack
- Otherwise
- considered[tex[i]] = true
- insert text[i] into stack
- increase i by 1
- if last_o[stack top] > i
- otherwise when stack top element < temp[i] and considered[text[i]] = false
- insert text[i] into stack
- considered[text[i]] := true
- increase i by 1
- otherwise increase i by 1
- if stack has no elements
- if text[i] is not present in last_o −
- return all of the elements of stack as string in reverse order
Let us see the following implementation to get better understanding −
Example
class Solution(object): def smallestSubsequence(self, text): """ :type text: str :rtype: str """ stack = [] last_o = {} considered = {} for i in range(len(text)-1,-1,-1): if text[i] not in last_o: last_o[text[i]] = i considered[text[i]] = False print(last_o) i = 0 while i < len(text): print(stack,i,text[i]) if len(stack) == 0: stack.append(text[i]) considered[text[i]] = True i+=1 elif stack[-1]>text[i] and considered[text[i]] == False: if last_o[stack[-1]]>i: considered[stack[-1]]=False stack.pop() else: considered[text[i]] = True stack.append(text[i]) i+=1 elif stack[-1]<text[i] and considered[text[i]] == False: stack.append(text[i]) considered[text[i]] = True i+=1 else: i+=1 return "".join(i for i in stack)
Input
"cdadabcc"
Output
"adbc"