• [LeetCode] 451. Sort Characters By Frequency


    Given a string s, sort it in decreasing order based on the frequency of characters, and return the sorted string.

    Example 1:

    Input: s = "tree"
    Output: "eert"
    Explanation: 'e' appears twice while 'r' and 't' both appear once.
    So 'e' must appear before both 'r' and 't'. Therefore "eetr" is also a valid answer.
    

    Example 2:

    Input: s = "cccaaa"
    Output: "aaaccc"
    Explanation: Both 'c' and 'a' appear three times, so "aaaccc" is also a valid answer.
    Note that "cacaca" is incorrect, as the same characters must be together.
    

    Example 3:

    Input: s = "Aabb"
    Output: "bbAa"
    Explanation: "bbaA" is also a valid answer, but "Aabb" is incorrect.
    Note that 'A' and 'a' are treated as two different characters.

    Constraints:

    • 1 <= s.length <= 5 * 105
    • s consists of English letters and digits.

    根据字符出现频率排序。

    题意是给定一个字符串,请将字符串里的字符按照出现的频率降序排列。注意此题的第三个例子,要求区分大小写。最优解是用到类似桶排序bucket sort的思路,也可以用 priority queue 做但是复杂度高。

    首先是桶排序。桶排序的思路用一个 hashmap 记录input里面所有出现过的字符和他们的频率,然后对hashmap(key, value)按照value大小对key重新排序。最后再按照各个字母出现的次数,拼接好最后的字符串。

    JavaScript实现

    时间O(nlogn) - need to sort the hashmap

    空间O(n) - hashmap

     1 /**
     2  * @param {string} s
     3  * @return {string}
     4  */
     5 var frequencySort = function (s) {
     6     let map = {};
     7     for (let letter of s) {
     8         if (map[letter]) {
     9             map[letter]++;
    10         } else {
    11             map[letter] = 1;
    12         }
    13     }
    14 
    15     let res = '';
    16     let sorted = Object.keys(map).sort((a, b) => map[b] - map[a]);
    17     for (let letter of sorted) {
    18         for (let i = 0; i < map[letter]; i++) {
    19             res += letter;
    20         }
    21     }
    22     return res;
    23 };

    Java实现

    时间O(n) - no need to sort anything

    空间O(n)

     1 class Solution {
     2     public String frequencySort(String s) {
     3         HashMap<Character, Integer> map = new HashMap<>();
     4         for (char c : s.toCharArray()) {
     5             map.put(c, map.getOrDefault(c, 0) + 1);
     6         }
     7 
     8         List<Character>[] bucket = new List[s.length() + 1];
     9         for (char key : map.keySet()) {
    10             int freq = map.get(key);
    11             if (bucket[freq] == null) {
    12                 bucket[freq] = new ArrayList<>();
    13             }
    14             bucket[freq].add(key);
    15         }
    16 
    17         StringBuilder sb = new StringBuilder();
    18         for (int i = bucket.length - 1; i >= 0; i--) {
    19             if (bucket[i] != null) {
    20                 for (char c : bucket[i]) {
    21                     for (int j = 0; j < map.get(c); j++) {
    22                         sb.append(c);
    23                     }
    24                 }
    25             }
    26         }
    27         return sb.toString();
    28     }
    29 }

    其次是用优先队列 priority queue。一开始还是用 hashmap 统计每个不同字母的出现次数,并把整个 map.entry 放入一个以 priority queue 构建的最大堆。堆顶元素是出现次数最多的字母。将每个字母写回 StringBuilder 的时候,我们还是按照出现次数从多到少往回写。

    时间O(nlogk)

    空间O(n) - priority queue

    Java实现

     1 class Solution {
     2     public String frequencySort(String s) {
     3         HashMap<Character, Integer> map = new HashMap<>();
     4         for (char c : s.toCharArray()) {
     5             map.put(c, map.getOrDefault(c, 0) + 1);
     6         }
     7 
     8         PriorityQueue<Map.Entry<Character, Integer>> queue = new PriorityQueue<>((a, b) -> b.getValue() - a.getValue());
     9         queue.addAll(map.entrySet());
    10 
    11         StringBuilder sb = new StringBuilder();
    12         while (!queue.isEmpty()) {
    13             Map.Entry e = queue.poll();
    14             for (int i = 0; i < (int) e.getValue(); i++) {
    15                 sb.append(e.getKey());
    16             }
    17         }
    18         return sb.toString();
    19     }
    20 }

    bucket sort相关题目

    LeetCode 题目总结

  • 相关阅读:
    操作系统进程通信
    操作系统进程调度
    java中的变量
    java移位运算符
    String, StringBuffer, StringBuilder 的区别
    多线程相关问题汇总
    java内存管理与GC机制(二)
    java内存管理与GC机制(一)
    进程与线程的理解
    Liferay7使用maven引入第三方jar包
  • 原文地址:https://www.cnblogs.com/cnoodle/p/12230497.html
Copyright © 2020-2023  润新知