携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第24天,点击查看活动详情
题目描述
给定一个字符串 s ,根据字符出现的 频率 对其进行 降序排序 。一个字符出现的 频率 是它出现在字符串中的次数。
返回 已排序的字符串 。如果有多个答案,返回其中任何一个。
示例 1:
输入: s = "tree"
输出: "eert"
解释: 'e'出现两次,'r'和't'都只出现一次。
因此'e'必须出现在'r'和't'之前。此外,"eetr"也是一个有效的答案。
示例 2:
输入: s = "cccaaa"
输出: "cccaaa"
解释: 'c'和'a'都出现三次。此外,"aaaccc"也是有效的答案。
注意"cacaca"是不正确的,因为相同的字母必须放在一起。
示例 3:
输入: s = "Aabb"
输出: "bbAa"
解释: 此外,"bbaA"也是一个有效的答案,但"Aabb"是不正确的。
注意'A'和'a'被认为是两种不同的字符。
解题思路
这道题没什么特别的,题意也很直接,就是按照字符串中字母出现的频率升序排序,出现次数最多的字母优先输出。
具体步骤如下:
- 我们可以创建一个对象
mp来记录每个单词的出现次数。 - 遍历字符串,统计每个字母的出现次数。
- 最后通过
Object.entries将对象mp转为键值对数组,然后通过sort以出现频率进行降序排序。 - 将排序后的键值对数组,对于每项元素
[k,v],进行k.repeat(v)操作复制v次之后拼接,就是最后的结果了。
更多关于 repeat 的详细内容:String.prototype.repeat() | MDN
题解
/**
* @param {string} s
* @return {string}
*/
var frequencySort = function (s) {
let m = {};
for (let w of s) {
m[w]++ || (m[w] = 1);
}
const arr = Object.entries(m).sort((a, b) => b[1] - a[1])
return arr.reduce((f, c) => {
return f + c[0].repeat(c[1]);
}, '');
};
解题思路——桶排序
桶排序需要一次遍历来统计最大的出现次数 maxCnt。然后初始化一个 length=maxCnt+1 大小的数组用来记录数据。
具体步骤如下:
- 初始化一个对象
mp用来统计每个字母的出现次数。 - 遍历字符串,统计每个字母的出现次数,同时更新最大出现次数
maxCnt。 - 遍历结束后初始化一个桶,为
length = maxCnt + 1的二维数组。 - 遍历 mp 对象,以每个字母的出现次数为下标,将该字母 push 到桶对应下标的数组中。
- 最后得到一个二维数组,其中每个元素都是一个数组,每个元素的下标表示当前下标对应的数组中的所有元素的出现次数。
- 统计结果。
题解
var frequencySort = function (s) {
const mp = {};
let maxFreq = 0;
for (const ch of s) {
mp[ch]++ || (mp[ch] = 1);
maxFreq = Math.max(maxFreq, mp[ch]);
}
const buckets = new Array(maxFreq + 1).fill(0).map(() => new Array());
for (const [ch, num] of Object.entries(mp)) {
buckets[num].push(ch);
}
return buckets.reduce((f, c, i) => {
return c.reduce((f2, c2) => {
return c2.repeat(i) + f2;
}, '') + f;
}, '');
};