[LeetCode 周赛183] 3. 最长快乐字符串(贪心、构造、巧妙解法)

1. 题目来源

链接:5195. 最长快乐字符串

2. 题目说明

在这里插入图片描述

3. 题目解析

方法一:贪心+构造+巧妙解法

这个问题其实正面考虑比较麻烦的。在此利用贪心的去构造会能直观简单点,下面谈谈构造策略:

  • 首先很直观的能够想到,若有多个字符,我们尽可能两两的将其放到一起,用另一个字母对其进行间隔。但是这对条件的判断以及特殊输入情况来讲就很麻烦,一度不知道如何去判断
  • 换一种构造策略,我们首先不考虑连续输出两字符,先考虑输出一个字符,那么一定是符合题意并且是最长的,那么可能会剩余一些字母,并且肯定已经有部分字母已经被用完了。这样我们就先构造出了 连续不相同的字符串
  • 接着我们将剩余字母向字符串进行回填,即若剩余字母 a,就将字符串中单个的 a 扩充成两个 a,这样也是肯定满足要求的并且还是最长的

即先填一个字符,若字符还有剩余,那么就将字符补充为两个,这样一定是合法且最长的。

在此贪心的进行构造,每次尝试进行构造时肯定是从当前字母个数最多的开始填充,这样才能构造出最长的连续字符串,一个排序函数就可以了。

在进行回填的时候,循环遍历字符串,并查看字符串每一位是否还有剩余字符,若仍存在剩余字符就填充一个进去,这样遍历完毕字符串就是满足题意的最长字符串了。很秒的思想!

构造方法多种多样,前几位大佬真的很快…

参见代码如下:

// 执行用时 :4 ms, 在所有 C++ 提交中击败了100.00%的用户
// 内存消耗 :6.5 MB, 在所有 C++ 提交中击败了100.00%的用户

int cnt[4], idx[4];
inline bool cmp(int a, int b) {return cnt[a] > cnt[b];}

class Solution {
public:
    char help(int x) {
        if (x == 1) return 'a';
        if (x == 2) return 'b';
        return 'c';
    }
    string longestDiverseString(int a, int b, int c) {
        vector<int> vt; vt.push_back(0);
        cnt[1] = a, cnt[2] = b, cnt[3] = c;
        idx[1] = 1, idx[2] = 2, idx[3] = 3;
        
        bool flag = true;
        while (flag) {
            sort(idx + 1, idx + 4, cmp);
            flag = false;
            for (int i = 1; i <= 3 and flag == false; ++i) {
                int c = idx[i];
                if (vt.back() != c and cnt[c] > 0) {
                    --cnt[c];
                    vt.push_back(c);
                    flag = true;
                }
            }
        }
        
        int len = vt.size();
        string ans = "";
        for (int i = 1; i < len; ++i) {
            ans += help(vt[i]);
            if (cnt[vt[i]] > 0) {
                ans += help(vt[i]);
                --cnt[vt[i]];
            }
        }
        
        return ans;
    }
};
发布了406 篇原创文章 · 获赞 368 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/yl_puyu/article/details/105336946