[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 题目总结

原文地址:https://www.cnblogs.com/cnoodle/p/12230497.html