[贪心]1405.最长快乐字符串.M

一、描述

1.如果字符串中不含有任何 ‘aaa’,‘bbb’ 或 ‘ccc’ 这样的字符串作为子串,那么该字符串就是一个「快乐字符串」
2.给你三个整数 a,b ,c,请你返回 任意一个 满足下列全部条件的字符串 s:
s 是一个尽可能长的快乐字符串。
s 中 最多 有a 个字母 ‘a’、b 个字母 ‘b’、c 个字母 ‘c’ 。
s 中只含有 ‘a’、‘b’ 、‘c’ 三种字母。
3.输入:a = 1, b = 1, c = 7
输出:“ccaccbcc"或者"ccbccacc”
// 0 <= a, b, c <= 100
// a + b + c > 0

二、解

简单来说就是给定a,b,c三个字符的数量,让我们去构成不含三个相同字符在一起的字符串,并且尽可能长
1.怎样构成的字符串最长
贪心策略:
(可以简单的看出,多的字符比少的字符用的次数多才行,这样才能构成最长)
每次选择个数最多的字符
情况1:一直到各个字符都为0,返回结果
情况2:当当前字符和字符串前两个字符相同(会构成aaa/…)时,选择第二个最多的字符,继续下一次判断;如果没有其他字符可选,返回结果
2怎样每次拿到最大剩余字符和最大剩余字符的下一个
1.用集合或者数组存放字符和个数,使用Comparator定义排序规则,使用时直接取第一个/第二个即可(不会取第三个)
2.优先队列PriorityQueue,(也是使用Comparator定义排序规则)
优先队列:

public static void main(String[] args) {

        int a = 1, b = 1, c = 7;
        System.out.println(longestDiverseString(a,b,c));

    }
    
    public static String longestDiverseString(int a, int b, int c) {

        StringBuilder sb = new StringBuilder();
        //注意Comparator<int[]>()使用int[]类型泛型,不然方法参数是object类型
//        PriorityQueue<int[]> priorityQueue = new PriorityQueue<>(new Comparator<int[]>() {
//            @Override
//            public int compare(int[] a1, int[] a2) {
//                return a2[0]-a1[0];
//            }
//        });
        //构建个数从小到大的优先队列,每次取的都会是最大的
        PriorityQueue<int[]> priorityQueue = new PriorityQueue<>((a1, a2) -> a2[0]-a1[0]);
        if (a>0){
            //int数组将char转为了int
            priorityQueue.add(new int[]{a,'a'});
        }
        if (b>0){
            priorityQueue.add(new int[]{b,'b'});
        }
        if (c>0){
            priorityQueue.add(new int[]{c,'c'});
        }
        //队列为空时退出
        while (!priorityQueue.isEmpty()){
            int[] curChar =priorityQueue.poll();
            int len = sb.length();
            //达到重复3个,前两个字符已经相同
            if (len>=2&&curChar[1]==sb.charAt(len-1)&&curChar[1]==sb.charAt(len-2)){
                //没有其他字符,直接返回
                if (priorityQueue.isEmpty()){
                    break;
                }
                int[] nextChar = priorityQueue.poll();
                sb.append((char)nextChar[1]);
                //这个字符剩余大于0才放回,否则就不放回
                if ((--nextChar[0])!=0){
                    priorityQueue.add(nextChar);
                }
                //放回没用到的char
                priorityQueue.add(curChar);
            }else {
                //未达到重复3个
                sb.append((char)curChar[1]);
                if ((--curChar[0])!=0){
                    priorityQueue.add(curChar);
                }
            }
        }
        return sb.toString();
    }

81 13 O(n∗k∗logC) O(1)

Tips

1.Comparator:
public interface Comparator
用于对集合进行排序,简单来说集合里加了这个就能自动排序了
主要是他的compare()
排序规则:
在这里插入图片描述

使compare(x, y) <= 0,即两个元素返回结果<=0就是正序,内部可按需要实现
如这里的要让最大的位于前面,就让后面的元素个数减前面元素个数,因为后面元素小于前面的元素,为负为正序,否则后面元素大于前面的元素为正会交换顺序
2.PriorityQueue(优先队列)
有顺序的队列,顺序可以自定义
逻辑结构为二叉树

其他

其实只要能获取最大值和第二个最大值都能有结果,这样消耗时间击败100%,但繁琐也不优雅

public static String longestDiverseString1(int a, int b, int c) {

        StringBuilder sb = new StringBuilder();
        while(true){
            char curChar = getMaxNumChar(a,b,c);
            if (curChar==' '){
                break;
            }
            int len = sb.length();
            if (len>=2&&curChar==sb.charAt(len-1)&&curChar==sb.charAt(len-2)){
                if (curChar=='a'){
                    a=a-101;
                }else if (curChar=='b'){
                    b=b-101;
                }else {
                    c=c-101;
                }
                char nextChar = getMaxNumChar(a,b,c);
                if (nextChar==' '){
                    break;
                }
                sb.append(nextChar);
                if (nextChar=='a'){
                    a=a-1;
                }else if (nextChar=='b'){
                    b=b-1;
                }else {
                    c=c-1;
                }
                if (curChar=='a'){
                    a=a+101;
                }else if (curChar=='b'){
                    b=b+101;
                }else {
                    c=c+101;
                }
            }else {
                sb.append(curChar);
                if (curChar=='a'){
                    a=a-1;
                }else if (curChar=='b'){
                    b=b-1;
                }else {
                    c=c-1;
                }
            }
        }
        return sb.toString();
    }

    //abc acb cab cba bac bca |A(3,3)
    public static char getMaxNumChar(int a, int b, int c){
        if (a>0&&a>=b&&a>c){
            return 'a';
        }else if(b>0&&b>=a&&b>=c) {
            return 'b';
        }else if(c>0){
            return 'c';
        }
        return ' ';
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值