1、桶排序,桶排序的话,适用于一些已经知道确定边界的一些数的排序,时间复杂度,可以做到n,不过空间复杂度也是n。
这里举个例子。比如,对1,3,4,2,3,9 进行排序。这里最小是1,最大是9,所以可以声明一个10长度的数组temp。初始化为0,如下图:
下面的是下标,然后就可以通过遍历上面需要排的数,比如遍历到1,就直接temp[1]++,那么就会使得1的值变成了1,然后遍历
3,temp[3]++,遍历完后,就可以了。入下图:
然后打印就遍历temp,只要不为0,就打印下标,同时值减一。直到减到0
@Test
public void bucket() {
int[] arrs = {1,3,4,2,3,9};
int[] temp = new int[10];
for(int i = 0; i< arrs.length; i++) {
temp[arrs[i]]++;
}
//打印相应的排序值
for(int i = 0; i< temp.length; i++) {
while(temp[i] > 0){
System.out.println(i);
temp[i]--;
}
}
}
下面介绍一个桶的运用。
在数组中(没有排序的),找出排好序后,相邻两个数差值最大的那个值。比如数组3,1,4,那么排好序的数组:1,3,4,则最大的差值maxDelta = 2
给出代码:
public static void main(String[] args) {
int[] arrs = { 100, 100,101 };
int bucket = bucket(arrs);
System.out.println(bucket);
}
/**
* 寻找排好序的数中,相邻两数差值最大的值。
*/
public static int bucket(int[] arrs) {
int min = Integer.MAX_VALUE;// 最小值
int max = Integer.MIN_VALUE;// 最大值
for (int i = 0; i < arrs.length; i++) {
min = Integer.min(arrs[i], min);
max = Integer.max(arrs[i], max);
}
//所有的数相等,最大差值为0
if(min == max) {
return 0;
}
int lent = arrs.length;
// 找到了最大值和最小值,然后进行分桶的操作,有lent+1个桶,lent+1个桶的原因是最大值和最小之间,肯定会有一个桶是空的
// , 那么相邻两个数的差值,最大肯定不会出现在桶内部,因为一个空桶之间的最近非空桶,相邻两个数的差值,肯定大于桶内的,所以
// 不考虑桶内的相邻差值,只考虑桶外,那么一个桶,就只需记录最大值和最小值就可以了。
boolean[] bucketFlag = new boolean[lent + 1];
int[] bucketMin = new int[lent + 1];
int[] bucketMax = new int[lent + 1];
// 这三个数组,分别是桶内的最大值和最小值和桶标记(桶是否进入过数)
bucketMin[0] = min;
bucketMax[lent] = max;
for (int i = 0; i < arrs.length; i++) {
//寻找数应该放入到哪个桶中。bucketId为桶标记
int bucketId = findBucket(arrs[i], lent, min, max);
//更新桶内的最大值和最小值,bucketFlag[bucketId]为false,说明没进过数,那么
//桶的最大值和最小值都是arrs[i],否则进行比较
bucketMin[bucketId] = bucketFlag[bucketId]?Integer.min(bucketMin[bucketId], arrs[i]): arrs[i];
bucketMax[bucketId] = bucketFlag[bucketId]?Integer.max(bucketMax[bucketId], arrs[i]): arrs[i];
//进入过数好,桶标记为true
bucketFlag[bucketId] = true;
}
int lastMax = bucketMax[0];
int maxDelta = 0;
int index = 1;
while(index < lent+1) {
//为非空桶时才操作
if(bucketFlag[index]) {
//当前桶的最小值减去上一个桶的最大值。跟maxDelta比较,保留大的值
maxDelta = maxDelta > (bucketMin[index] - lastMax) ? maxDelta : (bucketMin[index] - lastMax) ;
//记录上一个桶的最大值
lastMax = bucketMax[index];
}
index++;
}
return maxDelta;
}
private static int findBucket(int num, int lent, int min, int max) {
//(long)lent 这个是因为,值很大的时候,会超出Integer的最大值
//这个好难扣,扣不出来,就网上找了下这个公式
return (int) ((num - min) * (long)lent / (max - min));
}
这个运用,左老师说经常考,个人感觉,除了扣某个数属于哪个桶比较难,其他代码写起来比较简单点。其实我现在还是不会扣它属于哪个桶,我只是验证了这条式子是对的而已,怎么得出来的,还是不会。