[前端]_一起刷leetcode 451. 根据字符出现频率排序

429 阅读2分钟

大家好,我是挨打的阿木木,爱好算法的前端摸鱼老。最近会频繁给大家分享我刷算法题过程中的思路和心得。如果你也是想提高逼格的摸鱼老,欢迎关注我,一起学习。

题目

451. 根据字符出现频率排序

给定一个字符串,请将字符串里的字符按照出现的频率降序排列。

示例 1:

输入:
"tree"

输出:
"eert"

解释: 'e'出现两次,'r''t'都只出现一次。
因此'e'必须出现在'r''t'之前。此外,"eetr"也是一个有效的答案。

示例 2:

输入:
"cccaaa"

输出:
"cccaaa"

解释: 'c''a'都出现三次。此外,"aaaccc"也是有效的答案。
注意"cacaca"是不正确的,因为相同的字母必须放在一起。

示例 3:

输入:
"Aabb"

输出:
"bbAa"

解释: 此外,"bbaA"也是一个有效的答案,但"Aabb"是不正确的。
注意'A''a'被认为是两种不同的字符。

哈希表解法

思路

  1. map记录字符串中每个字符出现的次数;
  2. 对字符根据出现次数做一个从大到小的排序;
  3. 将字符根据出现的次数分别push进结果数组中;
  4. 将结果数组转成字符串。

实现

/**
 * @param {string} s
 * @return {string}
 */
var frequencySort = function(s) {
    let map = new Map();
    let arr = [];

    const n = s.length;
    for (let i = 0; i < n; i++) {
        // 如果出现过,加次数,没出现过的记录
        if (map.has(s[i])) {
            arr[map.get(s[i])].count++;
        } else {
            // 建立索引之间的关系
            map.set(s[i], arr.length);
            arr.push({ key: s[i], count: 1 });
        }
    }

    // 按照出现次数排序
    // 然后按出现次数push进结果中,最终转成字符串
    return arr.sort((a, b) => b.count - a.count).reduce((total, cur) => {
        while (cur.count) {
            total += cur.key;
            cur.count--;
        }

        return total;
    }, "");
};

桶排序

思路

  1. map记录字符串中每个字符出现的次数;
  2. 记录下最多的出现次数maxCount,然后创建出maxCount + 1个桶,每个桶里面是一个数组;
  3. 按出现的次数把它们放进各自的桶中;
  4. 从后面的桶依次往前取出元素;
  5. 将数组转成字符串。

这也是比较标准的用空间换时间的一种解决方案。

实现

/**
 * @param {string} s
 * @return {string}
 */
var frequencySort = function(s) {
    let map = new Map();
    let maxCount = 0;

    // 记录每个元素出现的次数,同时找到最多的次数
    const n = s.length;
    for (let i = 0; i < n; i++) {
        let cur = (map.get(s[i]) || 0) + 1
        map.set(s[i], cur);
        maxCount = Math.max(maxCount, cur);
    }

    let buckets = new Array(maxCount + 1).fill(0).map(v => new Array());

    // 按出现次数放进桶中
    for (let [key, value] of map) {
        buckets[value].push(key);
    }

    let result = "";

    // 依次从桶中拿出即可
    for (let i = maxCount; i > 0; i--) {
        for (let j = 0; j < buckets[i].length; j++) {
            for (let k = 1; k <= i; k++) {
                result += buckets[i][j];
            }
        }
    }

    return result;
};

看懂了的小伙伴可以点个关注、咱们下道题目见。如无意外以后文章都会以这种形式,有好的建议欢迎评论区留言。