Skip to content

Commit 34f3b8d

Browse files
committed
Update 0451. 根据字符出现频率排序.md
1 parent 66a2aec commit 34f3b8d

File tree

1 file changed

+47
-63
lines changed

1 file changed

+47
-63
lines changed

Solutions/0451. 根据字符出现频率排序.md

Lines changed: 47 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -5,65 +5,45 @@
55

66
## 题目大意
77

8-
给定一个字符串 `s`
8+
**描述**给定一个字符串 `s`
99

10-
要求:将字符串 `s` 里的字符按照出现的频率降序排列。
10+
**要求**:将字符串 `s` 里的字符按照出现的频率降序排列。如果有多个答案,返回其中任何一个
1111

12-
## 解题思路
12+
**说明**
13+
14+
- $1 \le s.length \le 5 * 10^5$。
15+
- `s` 由大小写英文字母和数字组成。
16+
17+
**示例**
18+
19+
```Python
20+
输入: s = "tree"
21+
输出: "eert"
22+
解释: 'e'出现两次,'r''t'都只出现一次。
23+
因此'e'必须出现在'r''t'之前。此外,"eetr"也是一个有效的答案。
24+
25+
26+
输入: s = "cccaaa"
27+
输出: "cccaaa"
28+
解释: 'c''a'都出现三次。此外,"aaaccc"也是有效的答案。
29+
注意"cacaca"是不正确的,因为相同的字母必须放在一起。
30+
```
1331

14-
使用哈希表统计字符频率。然后使用 `set` 集合对字符串去重并转换为 `list` 数组。
32+
## 解题思路
1533

16-
然后按照字符频数对新的字符串数组进行排序。将堆中频数最高的元素依次加入答案数组中,并不断调整剩余元素构成的大顶堆。
34+
### 思路 1:优先队列
1735

18-
最后输出答案数组。
36+
1. 使用哈希表 `s_dict` 统计字符频率。
37+
2. 然后遍历哈希表 `s_dict`,将字符以及字符频数存入优先队列中。
38+
3. 将优先队列中频数最高的元素依次加入答案数组中。
39+
4. 最后拼接答案数组为字符串,将其返回。
1940

20-
## 代码
41+
### 思路 1:代码
2142

2243
```Python
23-
class Solution:
24-
# 调整为大顶堆
25-
def heapify(self, nums, nums_dict, index, end):
26-
left = index * 2 + 1
27-
right = left + 1
28-
while left <= end:
29-
# 当前节点为非叶子节点
30-
max_index = index
31-
if nums_dict[nums[left]] > nums_dict[nums[max_index]]:
32-
max_index = left
33-
if nums_dict[nums[left]] == nums_dict[nums[max_index]]:
34-
if nums[left] > nums[max_index]:
35-
max_index = left
36-
if right <= end and nums_dict[nums[right]] > nums_dict[nums[max_index]]:
37-
max_index = right
38-
if right <= end and nums_dict[nums[right]] == nums_dict[nums[max_index]]:
39-
if nums[right] > nums[max_index]:
40-
max_index = right
41-
if index == max_index:
42-
# 如果不用交换,则说明已经交换结束
43-
break
44-
nums[index], nums[max_index] = nums[max_index], nums[index]
45-
# 继续调整子树
46-
index = max_index
47-
left = index * 2 + 1
48-
right = left + 1
49-
50-
# 初始化大顶堆
51-
def buildMaxHeap(self, nums, nums_dict):
52-
size = len(nums)
53-
# (size-2) // 2 是最后一个非叶节点,叶节点不用调整
54-
for i in range((size - 2) // 2, -1, -1):
55-
self.heapify(nums, nums_dict, i, size - 1)
56-
return nums
57-
58-
# 堆排序方法(本题未用到)
59-
def maxHeapSort(self, nums, nums_dict):
60-
self.buildMaxHeap(nums)
61-
size = len(nums)
62-
for i in range(size):
63-
nums[0], nums[size - i - 1] = nums[size - i - 1], nums[0]
64-
self.heapify(nums, nums_dict, 0, size - i - 2)
65-
return nums
44+
import heapq
6645

46+
class Solution:
6747
def frequencySort(self, s: str) -> str:
6848
# 统计元素频数
6949
s_dict = dict()
@@ -72,19 +52,23 @@ class Solution:
7252
s_dict[ch] += 1
7353
else:
7454
s_dict[ch] = 1
75-
76-
# 使用 set 方法去重,得到新数组
77-
new_s = list(s)
78-
size = len(new_s)
79-
# 初始化大顶堆
80-
self.buildMaxHeap(new_s, s_dict)
81-
res = list()
82-
for i in range(size):
83-
# 堆顶元素为当前堆中频数最高的元素,将其加入答案中
84-
res.append(new_s[0])
85-
# 交换堆顶和末尾元素,继续调整大顶堆
86-
new_s[0], new_s[size - i - 1] = new_s[size - i - 1], new_s[0]
87-
self.heapify(new_s, s_dict, 0, size - i - 2)
55+
56+
priority_queue = []
57+
for ch in s_dict:
58+
heapq.heappush(priority_queue, (-s_dict[ch], ch))
59+
60+
res = []
61+
while priority_queue:
62+
ch = heapq.heappop(priority_queue)[-1]
63+
times = s_dict[ch]
64+
while times:
65+
res.append(ch)
66+
times -= 1
8867
return ''.join(res)
8968
```
9069

70+
### 思路 1:复杂度分析
71+
72+
- **时间复杂度**:$O(n + k \times log_2k)$。其中 $n$ 为字符串 $s$ 的长度,$k$ 是字符串中不同字符的个数。
73+
- **空间复杂度**:$O(n + k)$。
74+

0 commit comments

Comments
 (0)