返回

用 JavaScript 解锁 LeetCode 的“最长快乐字符串”难题

前端

引言

对于算法爱好者来说,LeetCode 是一个磨练技能、解决难题的宝库。今天,我们将踏上激动人心的旅程,用 JavaScript 征服一道著名的 LeetCode 题目——“最长快乐字符串”。

问题表述

给定一个由小写字母组成的字符串 s,你的任务是构造一个最长的字符串 t,其中:

  • t 中每个字符都不同。
  • t 中每个字符出现在 s 中至少一次。

解决方案

为了解决这个问题,我们将采用一种贪心算法。贪心算法在每一步骤中做出看似最优的选择,最终得到一个整体最优解。

算法步骤

  1. 创建哈希表 :将 s 中每个字符及其出现次数存储在一个哈希表 hash 中。
  2. 排序哈希表 :根据字符出现次数从高到低对哈希表进行排序。
  3. 构造结果字符串
    • 从排序后的哈希表中取前三个出现次数最多的字符。
    • 将这三个字符按顺序附加到结果字符串 t 中。
    • 如果这三个字符的出现次数相同,则将出现次数最多的字符附加到 t 的末尾。
    • 将这三个字符从 hash 中移除。
  4. 重复步骤 3 :直到 hash 为空或 t 中字符总数达到 s 的长度。

JavaScript 代码

/**
 * 返回最长快乐字符串。
 *
 * @param {string} s 输入字符串
 * @return {string} 最长快乐字符串
 */
const longestDiverseString = (s) => {
  // 创建哈希表
  const hash = {};
  for (let i = 0; i < s.length; i++) {
    if (hash[s[i]]) {
      hash[s[i]]++;
    } else {
      hash[s[i]] = 1;
    }
  }

  // 排序哈希表
  const sortedHash = Object.entries(hash).sort((a, b) => b[1] - a[1]);

  // 构造结果字符串
  let t = "";
  while (sortedHash.length > 0 || t.length < s.length) {
    let top3 = sortedHash.slice(0, 3);
    if (top3[1] === top3[2]) {
      t += top3[0].repeat(2);
      sortedHash.shift();
      sortedHash.shift();
    } else {
      t += top3[0];
      sortedHash[0][1]--;
      if (sortedHash[0][1] === 0) {
        sortedHash.shift();
      }
    }
  }

  return t;
};

示例

输入:s = "leetcodeleet"
输出:"leetcodeleet"

结论

我们已经成功地用 JavaScript 编写了一个贪心算法来解决 LeetCode 的“最长快乐字符串”问题。通过排序哈希表和贪婪地选择出现次数最多的字符,我们的算法可以有效地构造满足问题要求的最长字符串。

拓展

  • 探索其他贪心算法及其在解决算法问题中的应用。
  • 研究 LeetCode 上的其他算法难题,并尝试用 JavaScript 编写解决方案。
  • 持续练习算法技能,不断提高问题解决能力。