分析&回答
动态演示
实现代码
/**
* 桶排序
* <p>
* 设置一个定量的数组当作空桶;
* 遍历输入数据,并且把数据一个一个放到对应的桶里去;
* 对每个不是空的桶进行排序;
* 从不是空的桶里把排好序的数据拼接起来。
*
* @param arr
*/
private static void bucketSort(int[] arr) {
int length = arr.length;
LinkedNode[] bucket = new LinkedNode[length]; // 桶的个数等于length
int max = arr[0]; // 求max
for (int i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
// 入桶
for (int i = 0; i < length; i++) {
int value = arr[i]; // 扫描每个元素
int hash = hash(arr[i], max, length); // 桶的下标
if (bucket[hash] == null) {
bucket[hash] = new LinkedNode(value); // 初始化链表
} else {
insertInto(value, bucket[hash], bucket, hash); // 插入链表
}
}
int k = 0; // 记录数组下标
// 出桶,回填arr
for (LinkedNode node : bucket) {
if (node != null) {
while (node != null) {
arr[k++] = node.value;
node = node.next;
}
}
}
}
// 根据桶的个数来确定hash函数,这份代码适合桶的个数等于数组长度
private static int hash(int element, int max, int length) {
return (element * length) / (max + 1);
}
private static void insertInto(int value, LinkedNode head, LinkedNode[] bucket, int hash) {
LinkedNode newNode = new LinkedNode(value);
// 小于头节点,放在头上
if (value <= head.value) {
newNode.next = head;
// 替换头节点
bucket[hash] = newNode;
return;
}
// 往后找第一个比当前值大的节点,放在这个节点的前面
LinkedNode p = head;
LinkedNode pre = p;
while (p != null && value > p.value) {
pre = p;
p = p.next;
}
if (p == null) { // 跑到末尾了
pre.next = newNode;
} else { // 插入pre和p之间
pre.next = newNode;
newNode.next = p;
}
}
/**
* 简单单向链表的节点
*/
class LinkedNode {
public int value;
public LinkedNode next;
public LinkedNode(int value) {
this.value = value;
}
}
性能分析
- 稳定
- 平均时间复杂度O(n + k)
- 空间复杂度O(n + k)
反思&扩展
喵呜面试助手: 一站式解决面试问题,你可以搜索微信小程序 [喵呜面试助手] 或关注 [喵呜刷题] -> 面试助手 免费刷题。如有好的面试知识或技巧期待您的共享!