贪心练习之最小字典序子串

题目描述

给定义一个全是小写字母的字符串str,请你删除多余字符,使得每种字符只剩下一个,并且让剩下的结果的字典序最小。

思路分析

此题是一种贪心策略,分析问题,题目是让删除多余字符,这说明,每种字符的保留区间是有限的。什么意思?比如,最后一个a字符在中间位置,那么,也就说,a字符最远就到中间了。同时,如果某个字符只有一个,比如在中间位置,那么,相当于这个字符的位置已经固定了。
下面介绍贪心策略:
先设计一张词频表,统计字符串中每个字符出现的次数。
然后,从头到尾遍历,每遇到一个字符,该词频–,直到遍历到某个字符的词频减完=0时,此时,停下来,从前面遍历过的所有字符中找出一个字典序最小的,确定下来一个字符,然后将选择位置的左边全部删除,后面所有这个字符也全部删除。再统计词频,继续下一轮。
为什么出现词频为0时停下呢?
这是因为,此时,说明停下位置的字符,后面就没有再出现了,如果我们继续往后,则选择的词是有可能在其右边,就会导致这个词漏掉。同时,我们在前面选择最小字典序的一个字符,有两种可能:
1、正好是当前词频为0的字符,则此时,其他字符词频不为0,后面还有,因此不会漏掉。
2、不是当前词频为0的字符,但是,词频为0的字符在最后的位置,因此,删除左边不可能漏掉。

代码

    public static String remove(String str){
        //小于等于1时,直接返回
        if(str==null || str.length()<2){
            return str;
        }
        //设置一个ACS码表长度的数组,用来统计词频
        int[] map= new int[256];
        //记录最小词频在str中的索引
        int minACSindez=0;
        for (int i = 0; i <str.length() ; i++) {
            //统计词频,对应ACS码的下标++
            map[str.charAt(i)]++;
        }
        for (int i = 0; i < str.length(); i++) {
            //如果出现词频减1为0,停止
            if(--map[str.charAt(i)]==0){
                break;
            }else {
                //否则就统计字典树最小的ACS码
                minACSindez=str.charAt(minACSindez)>str.charAt(i) ? i:minACSindez;
            }
        }
        //递归拼接后面的字符,
        //str.substring(minACSindez+1)用来删除index前面的
        //replaceAll(String.valueOf(str.charAt(minACSindez)),"")用来删除后面的所有相同字符
        return String.valueOf(str.charAt(minACSindez)) + remove(str.substring(minACSindez+1).replaceAll(String.valueOf(str.charAt(minACSindez)),""));
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值