1405.最长快乐字符串

难度:中等

目录

一、问题描述

二、思路

1、解题思路

2、极端情况判断

3、解决极端情况

三、解题

1、代码实现

2、时间复杂度 and 空间复杂度

四、总结


一、问题描述

这里直接采用LeetCode上面的描述。

如果字符串中不含有任何 'aaa''bbb''ccc' 这样的字符串作为子串,那么该字符串就是一个「快乐字符串」。

给你三个整数 abc,请你返回 任意一个 满足下列全部条件的字符串 s

  • s 是一个尽可能长的快乐字符串。
  • s 中 最多a 个字母 'a'b 个字母 'b'c 个字母 'c'
  • s 中只含有 'a''b''c' 三种字母。

如果不存在这样的字符串 s ,请返回一个空字符串 ""

下面给出示例:

提示:

  • 0 <= a, b, c <= 100
  • a + b + c > 0

二、思路

1、解题思路

        题目中说明了,不能允许重复的三个相同的字符连续出现,那么我们要优先使用数量最多的字符来进行排列。使用 贪心策略

在这里我们有两种方法来挑选最多的字符:

  • 每次根据数目,对字符进行排序
  • 使用 优先队列 会自动排序

我这里使用 优先队列 + 贪心策略

  1. 每次都选择 字符数量最多 的进行排列
  2. 如果 连续出现两个相同的字符 ,那么取字符数量 次多 的进行排列

重复操作,直至队列为空为止。

这里采用的优先队列结构如下:

  • priority_queue<pair<int,char>> pq;
  • int char 字符的个;
  • 这里 char 分别为字符 'a''b''c'

2、极端情况判断

  1. 这里在将第一多数量的字符出队后,如果 不存在 次多数量的字符,那么取 队头 元素时会溢出。

3、解决极端情况

  1. 在对 次多 数量的字符 取队头元素之前,要进行判断。如果此时队列是空,那么应该结束循环,因为再向字符串尾部添加字符,就会出现连续三个相同的字符,则不符合题意。

三、解题

1、代码实现

class Solution {
public:
    
    string longestDiverseString(int a, int b, int c) {
        //默认 大堆顶 优先
        priority_queue<pair<int,char>> pq;
        //优先队列存放三个 pair 
        if(a){
            pq.push({a,'a'});
        }
        if(b){
            pq.push({b,'b'});
        }
        if(c){
            pq.push({c,'c'});
        }
        string ans = "";
        while(!pq.empty()){
            pair<int,char> firstMax = pq.top();
            pq.pop();
            const int ansLength = ans.size();
            //如果是两个连续的 元素 那么 准备入队第二多的元素
            if(ansLength >= 2 and ans[ansLength-1] == firstMax.second and ans[ansLength-2] == firstMax.second){
                //这里判断一下 取完了最多的元素 还有没有元素在队列里面 否则 下面会越界
                if(pq.empty()){
                    break;
                }
                pair<int,char> secondMax = pq.top();
                pq.pop();
                ans.push_back(secondMax.second);
                secondMax.first -= 1;
                //第二多的元素还有的话,再次入队
                if(secondMax.first){
                    pq.push(secondMax);
                }
                //没有使用的 第一多的 元素重新入队
                pq.push(firstMax);
            }
            //否则 直接入队最多的元素 
            else{
                ans.push_back(firstMax.second);
                firstMax.first -= 1;
                // 第一多的元素 如果还有的话 再次入队
                if(firstMax.first){
                    pq.push(firstMax);
                }
            }
        }
        return ans;
    }
};

2、时间复杂度 and 空间复杂度

时间复杂度:O(a+b+c)*O(log(C))abc 分别为字符个数,这里 C 3 即字母个数,O(log(C))为入队后排序的时间复杂度。

空间复杂度:O(C)

四、总结

        使用 贪心策略,每次都找最优解,这里的最优解也就是 对 最多次多 的字符 进行排列,符合要求,直至全部排列完,或者剩下一种最多的字符 结束。

        再排列之前,每次都要根据字符数目,进行排序。理解这题能够稍微理解一些 贪心思想,这里使用 优先队列 ,也能够学习到优先队列的使用,分为 升序队列降序队列 (默认为 升序队列)。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_Alkaid_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值