1405.最长快乐字符串(贪心)

236 阅读3分钟

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

每日刷题第40天 2021.02.07

1405.最长快乐字符串

题目

  • 如果字符串中不含有任何 'aaa','bbb' 或 'ccc' 这样的字符串作为子串,那么该字符串就是一个「快乐字符串」。
  • 给你三个整数 a,b ,c,请你返回 任意一个 满足下列全部条件的字符串 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"
解释: 这是该测试用例的唯一正确答案。

提示

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

解法

  • 解题思路:贪心的思路
  • 分析题目:要求找到最长的快乐字符串,且快乐字符串中不包含三个连续相同的字母

贪心策略:

  • 尽可能优先(priority)使用当前最多的字母,因为最后剩下的一定是最多的字母,且只有一种字母会剩下。
  • 依次从当前最多的字母开始尝试。设:最终返回的最长快乐字符串为ans,将a,b,c存放进数组template中。
  • 每次调用sort()函数进行排序(排好序后的数组tempt),找到当前数量最多的,每次从中拿一个。当前最多的字符为tempt[0][0]
    • 如果ans长度小于2,直接拼接当前数量最多的字符即可。
    • ans长度大于2,比较tempt[0][0]ans[ans.length - 1]并且tempt[0][0]ans[ans.length - 2]是否相同,如果不相等,则将当前数量最多的字符拼接到结果字符串ans后面;
    • 反之,将第二多的字符中拿出一个,拼接到ans后面。
  • 两种结束情况:5 0 00 0 0,分别进行判断.

注意⚠️

  • 错误思路:每次放两个字母,不一定是对的。
  • 举例:比如a:5 ,b:2
    • 每次拿两个出来aabbaa
    • 正确答案:aabaaba
var longestDiverseString = function(a, b, c) {
  // 最长的快乐字符串:每次取最长的先放,因为最长的需要在前面消耗掉,不然到后面就会缩短快乐字符串的长度
  let ans = '';
  if(a == 0 && b == 0 && c == 0) return ans;
  let template = [['a',a],['b',b],['c',c]];

  // 比较函数
  let compare = function (template) {
    return template.sort((a,b) => b[1] - a[1]);
  }

  while(true){
    let tempt = compare(template);
    if(tempt[0][1] == 0) return ans;
    // 长度小于2的时候,直接放最长的即可
    if(ans.length < 2){
      ans += tempt[0][0];
      template[0][1]--;
    }else {
      // 长度大于等于2的时候,需要判断,下一个值存储什么
      let last = ans[ans.length - 1];
      if(last == tempt[0][0] && last == ans[ans.length - 2]) {
        // 两个条件均满足的时候,表示需要换次小于的来计算
        if(tempt[1][1] == 0) return ans;
        ans += tempt[1][0];
        template[1][1]--;
      }else {
        ans += tempt[0][0];
        template[0][1]--;
      }
    }
  }
};