题目

对于字符串x和y, 如果擦除x中的某些字母(有可能全擦掉或者都不擦)能够得到y,我们就称y是x的子序列。例如."ncd"是"nowcoder"的子序列,而"xt"不是。
现在对于给定的一个字符串s,请计算出字典序最大的s的子序列。

输入包括一行,一个字符串s,字符串s长度length(1 ≤ length ≤ 50).
s中每个字符都是小写字母

输出一个字符串,即字典序最大的s的子序列。

输入:test
输出:tt

思路

一开始想着回溯,或者用 indexOf 去循环判断,但都失败了!参考了一下大佬写法,总而言之是有规律的:

  • 总是在当前已经确定字符的后面的序列去查找
  • 确定字符字典序前面的总是比后面的大

那么,如果是从后往前看,就是总是找比当前字符字典序大于或者相等的字符,因为后面的字符有两种情况:

  • 字典序比前面的字符大
  • 字典序比前面的字符小或者相等

那么,如果一开始就从后往前去比较,就能保证确定字符总是合法的,同时发现,字符串最后一个字符总是能插入的。因为开头就要最大字典序的字符开头,最后一个字符字典序要么比前面都大或等于,要么比前面的小,都可以插入

所以,最后从后往前遍历原字符序列,使用双指针,去判断字符是否可以插入即可

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        char[] arr = br.readLine().toCharArray();
        StringBuilder sb = new StringBuilder();
        int p1 = arr.length - 1;//指向原字符序列待判断字符
        int p2 = p1; 
        while (p1 >= 0 && p2 >= 0) {
            if (arr[p1] >= arr[p2]) {
                sb.append(arr[p1]);
                p2 = p1;//如果确定了,那么下一次要比较的是上一个确定下来的字符
            }
            p1--;
        }
        System.out.println(sb.reverse().toString());
    }
}

总结

代码功底不好。。。不然回溯应该也可实现,下次继续挑战