算法题-根据字符出现频率排序

145 阅读2分钟

LeetCode:根据字符出现频率排序

给定一个字符串 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'被认为是两种不同的字符。

提示:

  • 1<=s.length<=51051 <= s.length <= 5 * 10^5
  • s 由大小写英文字母和数字组成

解题思路

先用hashmap存字母和字母出现的频率,再用list存map的键值对,利用collections的sort方法,自定义compareTo进行排序,按字母出现频率从大到小排序,最后遍历list,将字母按其频率写入String。

容易想到用哈希表将每个字符与其出现的频率映射起来,最后将频率排序,按照降序循环频率依次拼接字符串。

可以使用桶排序,将字符串的频率与字符映射,将频率设为桶的下标,每个桶内存放该频率的字符,可用StringBuilder数组来实现,既然要将频率设为下标,我们需要一个最大值来定义数组的长度,所以在创建map的同时更新维护一个最大值来生成桶,最终拼接字符串的时候从频率最大的开始拼接,同样实现排序。

另一种方式就是数据结构的模拟,桶排序的简化版,将桶的数据结构选择换成int数组的模式实现,用简单的数组来代替桶排序和哈希表,原理是相同的,可以定义二维数组,也可定义一维数组,且数组可用sort排序。

解题代码

public String frequencySort(String s) {
    char[] c = s.toCharArray();
    StringBuilder sb = new StringBuilder();
    Map < Character, Integer > map = new HashMap < > ();
    for (int i = 0; i < c.length; i++) {
        char x = c[i];
        map.put(x, map.getOrDefault(x, 0) + 1);
    }
    List < Character > list = new LinkedList < > (map.keySet());
    Collections.sort(list, (a, b) -> map.get(b) - map.get(a));
    for (int i = 0; i < list.size(); i++) {
        for (int j = 0; j < map.get(list.get(i)); j++) {
            sb.append(list.get(i));
        }
    }
    return sb.toString();
}

运行结果

Snipaste_2023-06-24_23-08-54.png

复杂度详情

  • 空间复杂度:O(1)O(1)
  • 时间复杂度:O(n)O(n)

掘金(JUEJIN)一起进步,一起成长!