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(); } }