1. 桶排序算法精讲与高频题目实战
桶排序(Bucket Sort)是一种非常实用的非比较排序算法,特别适合处理数据分布均匀且范围已知的场景。与快速排序、归并排序等基于比较的排序算法不同,桶排序通过将数据分配到有限数量的"桶"中,再对每个桶中的数据进行排序,最后按顺序合并所有桶中的数据,从而达到整体有序的效果。
1.1 桶排序的核心思想
桶排序的工作流程可以分为三个关键步骤:
-
分配阶段:根据元素的关键值,将它们分配到不同的桶中。这个分配过程通常通过一个映射函数完成,该函数将元素值转换为桶的索引。
-
排序阶段:对每个非空桶中的元素进行排序。可以使用任何合适的排序算法,如插入排序、快速排序等。
-
收集阶段:按顺序遍历所有桶,将桶中的元素依次取出,合并成最终的有序序列。
桶排序的时间复杂度取决于数据的分布情况和桶的数量。在理想情况下,当数据均匀分布在各个桶中时,桶排序的时间复杂度可以达到O(n)。但在最坏情况下,如果所有元素都集中在同一个桶中,时间复杂度会退化为O(n²)。
1.2 桶排序的适用场景
桶排序特别适合以下场景:
- 输入数据均匀分布在一个范围内
- 需要处理的数据量较大
- 数据的关键值范围已知且有限
- 需要稳定的排序结果(当使用稳定排序算法对桶内元素排序时)
在实际应用中,桶排序常用于处理频率统计、数据分箱等问题,这也是为什么它在解决"前K个高频元素"这类问题时表现出色。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 力扣高频题目解析
2.1 451. 根据字符出现频率排序
这道题目要求我们根据字符串中字符的出现频率对其进行排序,出现频率高的字符排在前面,频率相同的字符则按任意顺序排列。
2.1.1 基本解法
cpp复制class Solution {
public:
string frequencySort(string s) {
int MAX = 0;
int cnt[256] = {0};
// 统计每个字符的出现频率
for(int i = 0; i < s.size(); i++) {
cnt[(int)s[i]]++;
MAX = max(MAX, cnt[(int)s[i]]);
}
string t;
// 从最高频率开始,构建结果字符串
for(int i = MAX; i > 0; i--) {
for(int j = 0; j < 256; j++) {
if(cnt[j] == i) {
t.append(cnt[j], j);
}
}
}
return t;
}
};
这个解法使用了桶排序的思想:
- 首先统计每个字符的出现频率
- 然后从最高频率开始,将字符按频率降序添加到结果字符串中
注意:这里使用了固定大小的数组(256)来统计ASCII字符的频率,这是一种空间换时间的优化策略。
2.1.2 优化解法
cpp复制class Solution {
public:
string frequencySort(string s) {
