[路飞]_字符频次唯一的最小删除次数

144 阅读2分钟

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

1647. 字符频次唯一的最小删除次数

题目

如果字符串 s 中 不存在 两个不同字符 频次 相同的情况,就称 s 是 优质字符串 。

给你一个字符串 s,返回使 s 成为 优质字符串 需要删除的 最小 字符数。

字符串中字符的 频次 是该字符在字符串中的出现次数。例如,在字符串 "aab" 中,'a' 的频次是 2,而 'b' 的频次是 1 。

  • 数据量10510^5
  • 字符串仅含小写英文字母

示例1

输入: s = "aab"
输出: 0
解释: s 已经是优质字符串。

示例2

输入:s = "aaabbbcc"
输出:2
解释:可以删除两个 'b' , 得到优质字符串 "aaabcc" 。
另一种方式是删除一个 'b' 和一个 'c' ,得到优质字符串 "aaabbc" 

题解

常规思路+哈希表

已知字符串仅含小写英文字母,记录频次。这类问题可以压缩数据量,将字符串放入长度为26的数组中,数组下标表示字符串,数组元素表示字符串存在的数量。

比如字符串s = "aaabbbcc",字符串可以映射为数组下标[a,b,...,y,x] => [0,1,...,24,15]

  • 假设数组list表示长度为26的数组,将字符串数据写入list数组,数组下标表示字符串,元素表示此字符串出出现的频次list = [3,3,2,0,...,0]
  • 使用map记录list数组元素,因为重复的元素表示两个不同字符频次相同,需要删除相同频次的字符串,将重复的元素放入arry数组
  • 枚举array数组,将array数组元素作为字符频次数量,迭代递减,迭代终止条件频次数量 或者 map中不存在这个数量
  • 使用result变量记录迭代递减次数
  • 返回result

整个过程逻辑还是比较清晰的

根据上述思路编辑代码如下:

代码

var minDeletions = function (s) {
  const list = Array(26).fill(0);
  for (let i = 0; i < s.length; i++) {
    const k = s[i];
    const idx = k.charCodeAt() - 'a'.charCodeAt();
    list[idx]++;
  }
  const map = {};
  let array = [];
  for (let i = 0; i < 26; i++) {
    const k = list[i];
    if (k === 0) continue;
    if (map[k]) {
      array.push(k);
    } else {
      map[k] = 1;
    }
  }
  let result = 0;
  for (let i = 0; i < array.length; i++) {
    let c = array[i];
    while (map[c]) {
      c--;
      result++;
    }
    if (c > 0) map[c] = 1;
  }
  return result;
};