内容来自刘宇波老师算法与数据结构体系课
1、MSD 与 Bucket


2、桶排序原理


3、桶排序实现一
| |
| |
| |
| public class BucketSort { |
| |
| private BucketSort() { |
| } |
| |
| public static void sort(Integer[] arr, int B) { |
| if (B <= 1) throw new IllegalArgumentException("B must be > 1"); |
| sort(arr, 0, arr.length - 1, B, new Integer[arr.length]); |
| } |
| |
| |
| |
| |
| private static void sort(Integer[] arr, int left, int right, int B, Integer[] temp) { |
| if (left >= right) return; |
| |
| int minV = Integer.MAX_VALUE; |
| int maxV = Integer.MIN_VALUE; |
| for (int i = left; i <= right; i++) { |
| minV = Math.min(minV, arr[i]); |
| maxV = Math.max(maxV, arr[i]); |
| } |
| if (minV == maxV) return; |
| |
| int d = (maxV - minV + 1) / B + ((maxV - minV + 1) % B != 0 ? 1 : 0); |
| |
| int[] cnt = new int[B]; |
| int[] index = new int[B + 1]; |
| |
| for (int i = left; i <= right; i++) cnt[(arr[i] - minV) / d]++; |
| for (int i = 0; i < B; i++) index[i + 1] = index[i] + cnt[i]; |
| for (int i = left; i <= right; i++) { |
| int p = (arr[i] - minV) / d; |
| temp[left + index[p]] = arr[i]; |
| index[p] += 1; |
| } |
| System.arraycopy(temp, left, arr, left, right - left + 1); |
| |
| |
| |
| sort(arr, left, left + index[0] - 1, B, temp); |
| for (int i = 0; i + 1 <= B - 1; i++) { |
| sort(arr, left + index[i], left + index[i + 1] - 1, B, temp); |
| } |
| } |
| } |
4、更简单的桶排序


5、桶排序实现二
| |
| |
| |
| public class BucketSort { |
| |
| private BucketSort() { |
| } |
| |
| public static void sort(Integer[] arr, int c) { |
| |
| if (c <= 0) throw new IllegalArgumentException("c must be > 0"); |
| |
| int minV = Integer.MAX_VALUE; |
| int maxV = Integer.MIN_VALUE; |
| for (int num : arr) { |
| minV = Math.min(minV, num); |
| maxV = Math.max(maxV, num); |
| } |
| if (minV == maxV) return; |
| |
| int range = maxV - minV + 1; |
| int B = range / c + (range % c != 0 ? 1 : 0); |
| LinkedList<Integer>[] buckets = new LinkedList[B]; |
| for (int i = 0; i < B; i++) buckets[i] = new LinkedList<>(); |
| |
| for (Integer num : arr) buckets[(num - minV) / c].add(num); |
| for (int i = 0; i < B; i++) Collections.sort(buckets[i]); |
| int index = 0; |
| for (int i = 0; i < B; i++) { |
| for (int num : buckets[i]) arr[index++] = num; |
| } |
| } |
| } |
6、桶排序实现三
| |
| |
| |
| public class BucketSort { |
| |
| private BucketSort() { |
| } |
| |
| public static void sort(Integer[] arr, int c) { |
| |
| if (c <= 0) throw new IllegalArgumentException("c must be > 0"); |
| |
| int minV = Integer.MAX_VALUE; |
| int maxV = Integer.MIN_VALUE; |
| for (Integer num : arr) { |
| minV = Math.min(minV, num); |
| maxV = Math.max(maxV, num); |
| } |
| if (minV == maxV) return; |
| |
| int range = maxV - minV + 1; |
| int B = range / c + (range % c != 0 ? 1 : 0); |
| Integer[][] buckets = new Integer[B][c]; |
| int[] size = new int[B]; |
| |
| for (Integer num : arr) { |
| int p = (num - minV) / c; |
| Integer[] bucket = buckets[p]; |
| if (size[p] == bucket.length) { |
| resize(buckets, p); |
| bucket = buckets[p]; |
| } |
| bucket[size[p]++] = num; |
| } |
| for (int i = 0; i < B; i++) InsertionSort.sort(buckets[i], 0, size[i] - 1); |
| |
| int index = 0; |
| for (int i = 0; i < B; i++) { |
| Integer[] bucket = buckets[i]; |
| for (int j = 0; j < size[i]; j++) arr[index++] = bucket[j]; |
| } |
| } |
| |
| private static void resize(Integer[][] buckets, int p) { |
| Integer[] bucket = buckets[p]; |
| Integer[] newBucket = new Integer[(int) (bucket.length * 1.5)]; |
| System.arraycopy(bucket, 0, newBucket, 0, bucket.length); |
| buckets[p] = newBucket; |
| } |
| } |
7、复杂度分析
| 在第三版桶排序中 |
| |
| 数据量是 N,数据范围是 range |
| 每个桶有 c 范围个元素,共 range / c 个桶 |
| 假设数量比较平均的落到桶中,每个桶的元素个数大约是 Nc / range |
| 每个桶采用插入排序:(Nc / range)^2 |
| |
| 整体:(range / c) * (Nc / range)^2 = (N^2 * c / range) |
| 在我的测试用例中,N 约等于 range,最终的复杂度大约是 Nc |

8、最大间距
164 - 最大间距
| public class MaximumGap { |
| |
| public static int maximumGap(int[] nums) { |
| if (nums.length < 2) return 0; |
| |
| int minV = Integer.MAX_VALUE; |
| int maxV = -1; |
| for (int num : nums) { |
| minV = Math.min(minV, num); |
| maxV = Math.max(maxV, num); |
| } |
| |
| |
| int minSpacing = (maxV - minV) / (nums.length - 1) + ((maxV - minV) % (nums.length - 1) != 0 ? 1 : 0); |
| |
| |
| |
| int c = minSpacing + 1; |
| int range = maxV - minV + 1; |
| int B = range / c + (range % c != 0 ? 1 : 0); |
| if (B == 1) return minSpacing; |
| int[] min = new int[B]; |
| int[] max = new int[B]; |
| Arrays.fill(min, Integer.MAX_VALUE); |
| Arrays.fill(max, -1); |
| for (int num : nums) { |
| int p = (num - minV) / c; |
| min[p] = Math.min(min[p], num); |
| max[p] = Math.max(max[p], num); |
| } |
| |
| int res = 0; |
| int lastMax = max[0]; |
| for (int i = 1; i < B; i++) { |
| if (min[i] == Integer.MAX_VALUE) continue; |
| res = Math.max(res, min[i] - lastMax); |
| lastMax = max[i]; |
| } |
| |
| return res; |
| } |
| |
| public static void main(String[] args) { |
| |
| int[] nums = {1, 1, 1, 1, 1, 1, 1, 2}; |
| System.out.println(maximumGap(nums)); |
| } |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步