桶结构:利用数组实现。即一个萝卜一个坑
利用桶进行的排序算法:对数据有一定的要求(这也是桶排序的瓶颈)
-
计数排序
-
基数排序
- 利用桶结构来解决实际问题:
给定一个数组,求在数组有序的情况下,相邻的两个数的最大差值,时间复杂度控制在O(N),且不可用非基于比较的排序。
public class Bucket {
public static int maxGap(int[] arr) {
if (arr.length <= 1)
return 0;
int res = 0;
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
//找出数组的最大值和最小值
for (int i = 0; i < arr.length; i++) {
min = Math.min(min, arr[i]);
max = Math.max(max, arr[i]);
}
if(max == min)
return 0;
//开辟两个长度为N+1的数组,模拟桶的概念,一个存放当前桶的最大值,一个存储当前桶的最小值,也可以用二维数组
int[] maxArr = new int[arr.length + 1];
int[] minArr = new int[arr.length + 1];
//把min和max放在对应的位置上
minArr[0] = min;
maxArr[maxArr.length - 1] = max;
//开辟标志数组,表示桶中是否存放了数字
boolean[] flag = new boolean[arr.length + 1];
for (int i = 0; i < flag.length; i++)
flag[i] = false;
//开始遍历数组
for(int i = 0; i < arr.length; i++)
{
int index = bucket(arr[i], max,min,arr.length);
minArr[index] = flag[index] ? Math.min(minArr[index], arr[i]) : arr[i];
maxArr[index] = flag[index] ? Math.max(minArr[index], arr[i]) : arr[i];
flag[index] = true;
}
//不能这样写,因为有空桶,我们必须记录上一个非空桶的值
// for(int j = 1; j < arr.length; j++)
// {
// if(flag[j])
// res = Math.max(res, minArr[j] - maxArr[j - 1]);
// }
//最大的差值一定是相邻两个桶中的最值的差值
int lastMax = maxArr[0];
int i = 1;
for (; i <= arr.length; i++) {
if (flag[i]) {
res = Math.max(res, minArr[i] - lastMax);
lastMax = maxArr[i];
}
}
return res;
}
//将数字放入对应的桶:给定一个长度为N的数组,存放规则为将数组出现的最大范围平分成N份,
// (data - min)/ (max - min) 是表示当前所求的数在整个范围的比例,
// 换句话说,这个比值一定小于1,乘上数组的长度就表示这个数要落在什么桶中
public static int bucket(int data,int max,int min,int length)
{
return ((data - min) * length / (max - min));
}
public static void main(String[] args) {
int[] arr = {4,3,6,2,1,9,234,1234};
System.out.println(maxGap(arr));
}
}