leetcode5086java
給定一個字符串s,其中只包含小寫字母。求s的一個子序列t。要求t包含s中的所有字符。若是答案有多個,輸出字典序最小的那個子序列。app
首先,爲s中每一個字符打標籤,表示該字符是否爲其類型中的最後一個字符
其次,從左往右掃描s,讓每一個字符進棧。進棧過程當中知足以下約束:ui
import java.util.Arrays; class Solution { public String smallestSubsequence(String text) { //初始化isLast boolean[] isLast = new boolean[text.length()]; boolean[] had = new boolean[26]; for (int i = text.length() - 1; i >= 0; i--) { int c = text.charAt(i) - 'a'; if (!had[c]) { had[c] = true; isLast[i] = true; } else { isLast[i] = false; } } int[] sta = new int[text.length()];//定義一個棧,棧中存放的是字符的下標 int si = 0;//定義一個棧頂指針 int[] indexOf = new int[26];//每類字符在棧中的位置 Arrays.fill(indexOf, -1);//-1表示字符不在棧中 for (int i = 0; i < text.length(); i++) { char c = text.charAt(i); if (indexOf[c - 'a'] != -1) {//棧中已經包含了此字符,則使用最新字符更新之,這個地方很關鍵 sta[indexOf[c - 'a']] = i; continue; } while (si > 0) {//當能夠彈棧的時候儘可能彈棧 int pos = sta[si - 1];//棧頂元素的下表 if (isLast[pos]) break;//若是棧頂元素是該類字符中的最後一個,那麼不能彈 char top = text.charAt(pos);//棧頂字符 if (top < c) break;//若是棧頂字符小於當前字符,中止彈棧 //不然,執行彈棧 indexOf[top - 'a'] = -1; si--;//彈棧 } sta[si++] = i;//當前元素入棧 indexOf[c - 'a'] = si - 1; } //構造答案 StringBuilder ans = new StringBuilder(); for (int i = 0; i < si; i++) ans.append(text.charAt(sta[i])); return ans.toString(); } }