力扣0207-1405. 最长快乐字符串

312 阅读2分钟

「这是我参与2022首次更文挑战的第14天,活动详情查看:2022首次更文挑战」。

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

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

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

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

示例 1:

输入:a = 1, b = 1, c = 7
输出:"ccaccbcc"
解释:"ccbccacc" 也是一种正确答案。

示例 2:

输入:a = 2, b = 2, c = 1
输出:"aabbc"

示例 3:

输入:a = 7, b = 1, c = 0
输出:"aabaa"
解释:这是该测试用例的唯一正确答案。

贪心

题目要求找到最长的快乐字符串,且快乐字符串中不含有三个连续相同的字母。为了找到最长的字符串,我们可以使用如下贪心策略:

  • 尽可能优先使用当前数量最多的字母,因为最后同一种字母剩余的越多,越容易出现字母连续相同的情况。如果构建完成最长的快乐字符串后还存在剩余未选择的字母,则剩余的字母一定为同一种字母且该字母的总数量最多。
  • 依次从当前数量最多的字母开始尝试,如果发现加入当前字母会导致出现三个连续相同字母,则跳过当前字母,直到我们找到可以添加的字母为止。实际上每次只会在数量最多和次多的字母中选择一个。
  • 如果尝试所有的字母都无法添加,则直接退出,此时构成的字符串即为最长的快乐字符串。
var longestDiverseString = function(a, b, c) {
    const res = [];
    const arr = [[a, 'a'], [b, 'b'], [c, 'c']];
    
    while (true) {
        arr.sort((a, b) => b[0] - a[0]);
        let hasNext = false;
        for (const [i, [c, ch]] of arr.entries()) {
            if (c <= 0) {
                break;
            }
            const m = res.length;
            if (m >= 2 && res[m - 2] === ch && res[m - 1] === ch) {
                continue;
            }
            hasNext = true;
            res.push(ch);
            arr[i][0]--;
            break;
        }
        if (!hasNext) {
            break;
        }
    }
    
    return res.join('');
};

复杂度分析

  • 时间复杂度:O((a+b+c)×ClogC)O((a+b+c)×Clog⁡C),其中 a,b,ca,b,c 为给定的整数,C 表示字母的种类,在本题中 C=3C=3。每次从待选的字母中选择一个字母需要执行一次排序,时间复杂度为 O(ClogC)O(Clog⁡C),最多需要选择 a+b+ca+b+c个字母。
  • 空间复杂度:O(C)O(C),在本题中 C=3C=3。需要 O(C)O(C) 的空间存储字母的当前计数。