「这是我参与2022首次更文挑战的第16天,活动详情查看:2022首次更文挑战」
题目
1647. 字符频次唯一的最小删除次数
如果字符串 s 中 不存在 两个不同字符 频次 相同的情况,就称 s 是 优质字符串 。
给你一个字符串 s,返回使 s 成为 优质字符串 需要删除的 最小 字符数。
字符串中字符的 频次 是该字符在字符串中的出现次数。例如,在字符串 "aab" 中,'a' 的频次是 2,而 'b' 的频次是 1 。
示例 1:
输入:s = "aab"
输出:0
解释:s 已经是优质字符串。
示例 2:
输入:s = "aaabbbcc"
输出:2
解释:可以删除两个 'b' , 得到优质字符串 "aaabcc" 。
另一种方式是删除一个 'b' 和一个 'c' ,得到优质字符串 "aaabbc" 。
示例 3:
输入:s = "ceabaacb"
输出:2
解释:可以删除两个 'c' 得到优质字符串 "eabaab" 。
注意,只需要关注结果字符串中仍然存在的字符。(即,频次为 0 的字符会忽略不计。)
解法一
遍历,去重。
思路
首先我们要知道,如果遇到有两个字符频率一样,那么我将一个频率减1之后,如果还有元素和当前元素,那就还得继续减1,知道没有频率相同为止,也就是说,这个规律,没有什么套路。
例1:
aaabbbcc,我们将a频率减1,那a和c频率都为2,我们还得把a频率再降1才行
例2:
aaaaabbbbbccccdddee,这个我们将频率写出来为,554321,那将a降为4,a又和c冲突了,再降1又和d冲突了,所以我们得一直降,降到a只剩一个,则更其他人不冲突。
那我们的逻辑也很简单。
- 先把每个字符的频率计算出来,放在一个数组里。
- 用一个set来存字符出现的频率
- 遍历所有字符
- 如果当前字符的频率在set中没有重复的,则将它加入set
- 如果当前字符的频率在set中有重复的,则将当前字符频率减一,继续判断
- 频率每次减一,就把处理次数加1
- 最终返回处理次数即可
代码如下
/**
* @param {string} s
* @return {number}
*/
var minDeletions = function (s) {
let arr = s.split('').map((item) => {
return item.charCodeAt()
});
let count = new Array(26).fill(0);
let result = 0;
let set = new Set();
for (let i = 0; i < arr.length; i++) {
count[arr[i] - 'a'.charCodeAt()]++;
}
for (let i = 0; i < 26; i++) {
let k = count[i];
while (k > 0) {
if (set.has(k)) {
k--;
result++;
}
else {
set.add(k);
break;
}
}
}
return result;
}
复杂度分析
时间复杂度:O(n),第一次处理字符的频率为一个数组为O(n),后面遍历时间复杂度最坏情况为O(n),即每个元素都只有一个,故总共取O(n)。
空间复杂度:O(n),将字符串处理成数组需要O(n)。