122 删除多余的字符得到字典序最小的字符串
Table of Contents

ac

给一个全是小写字母的字符串str,删除多余字符,使得每种字符只保留一个,并且让最终结果字符串字典序最小。

基于已存在的和后面的字符做加入,删除操作

  1. 依次取当前字符,若栈为空或者大于栈顶字符(且栈中不存在该字符),就放入

  2. 小于栈顶元素,就查看栈顶元素在字符串后面有没有存在的,有的话就弹出,直到栈为空或字符串没有存在相同元素;然后放入该新字符。

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;

public class Main {
    public static Scanner sc = new Scanner(System.in);

    public static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

    public static void main(String[] args) throws Exception {
        String s = sc.nextLine();
//        String s = "dbcacbca";

        int n = s.length();
        char[] chars = s.toCharArray();

        // 统计出现次数
        int[] cnt = new int[255];
        for(int i=0;i<n;i++){
            cnt[chars[i]] ++;
        }
        // 统计是否当前被使用给过了
        boolean[] vis = new boolean[255];
        // 收集结果的栈
        Stack<Character> sta = new Stack<>();
        for(int i=0;i<n;i++){
            cnt[chars[i]] --; // 用一个少一次
            if(sta.isEmpty() && vis[chars[i]] == false){
                sta.push(chars[i]);
                vis[chars[i]] = true;
            }else {
                Character topChar = sta.peek();
                if(chars[i] > topChar && vis[chars[i]] == false){
                    sta.push(chars[i]);
                    vis[chars[i]] = true;
                }
                if(chars[i] < topChar && vis[chars[i]] == false){
                    while (!sta.isEmpty() && sta.peek() > chars[i] && cnt[sta.peek()] > 0){
                        vis[sta.peek()] = false;
                        sta.pop();
                    }
                    sta.push(chars[i]);
                    vis[chars[i]] = true;
                }
            }
        }
        // 输出结果
        char[] ans = new char[sta.size()];
        int ansIndex = ans.length - 1;
        while(!sta.empty()){
            ans[ansIndex --] = sta.peek();
            sta.pop();
        }
        System.out.println(ans);
    }

}
/*
dbcacbca

dabc
*/