排序---桶排序
作者:互联网
7.桶排序
桶排序不同与前几种排序,它不是基于比较的排序方式,而是基于数据状况的排序,我们设置一个定量的数组当做空桶子,寻访序列,并且把项目一个一个放到对应的桶子去,对每个不是空的桶子进行排序,从不是空的桶子里把项目再放回原来的序列,排序结束。
基于桶排序的计数排序,时间复杂度为O(n),空间复杂度也为O(n)
public class Sort{
public static void bucketSort(int []arr){
if(arr==null||arr.length<2)
return ;
int max=Integer.MIN_VALUE;
for(int i=0;i<arr.length;i++){
max=Math.max(max,arr[i]);
}
int []bucket=new int[max+1]; //桶的下标代表数组中数值的大小,所以桶的长度要为数组中的最大值
for(int i=0;i<arr.length;i++){
bucket[arr[i]]++; //记数排序,相同值出现的次数
}
int i=0;
for(int j=0;j<bucket.length;j++){
while(bucket[j]-->0)
arr[i++]=j //将排好的数存会原数组
}
}
}
基于桶的概念延伸出来的一道题,对于一个无序数组,我们希望得出有序后相邻两个数间最大的差值。时间复杂度要求O(n)
public class MaxGap{
public static int maxGap(int []nums){
if(nums==null||nums.length<2)
return 0;
int len=nums.length;//记录数组的长度
int min=Integer.MAX_VALUE; //数组中最小的元素
int max=Integer.MIN_VALUE;//数组中最大的元素
for(int i=0;i<len;i++){
min=Math.min(min,nums[i]);
max=Math.max(max,nums[i]);
}
if(min==max)
return 0;
//桶的数量为数组的长度加一,
boolean []hasNum=new boolean[len+1]; //表示桶里是否有数字
int []maxs=new int[len+1];
int []mins=new int[len+1]; //每个桶中只存放这个桶内的最大值和最小值
int bid=0; //桶的下标
for(int i=0;i<len;i++){
bid=bucket(nums[i],len,min,max); //nums[i]应该放到哪个桶里
mins[bid]=hasNum[bid]?Math.min(mins[bid],nums[i]):nums[i];
maxs[bid]=hasNum[bid]?Math.max(maxs[bid],nums[i]):nums[i];
hasNum[bid]=true;
}
//计算相邻非空桶中左桶的最大值和右桶的最小值的差值,找到最大的返回。
int res=0;
int lastMax=maxs[0]; //非空左桶的最大值
int i=1;
for(;i<=len;i++){
if(hasNum[i]){
res=Math.max(res,mins[i]-lastMax);
lastMax=maxs[i];
}
}
return res;
}
public static int bucket(long num,long len,long min,long max){//计算num应该存放在哪个桶
return (int)((num-min)*len/(max-min));
}
}
桶排序的延伸题目:
出现频率最多的K个数
347. Top K Frequent Elements (Medium)
Given [1,1,1,2,2,3] and k = 2, return [1,2].
设置若干个桶,每个桶存储出现频率相同的数,并且桶的下标代表桶中出现数的频率,即第i个桶中存储的数出现的频率就是i。
把数都放到桶之后,从后向前遍历桶,最先得到的k个数就是出现频率最多的k个数。
public List<Integer>topKFrequent(int []nums,int k){
Map<Integer,Integer>map=new HashMap<>();
for(int i=0;i<nums.length;i++){
map.put(nums[i],map.getOrDefault(nums[i],0)+1);
}
List []bucket=new ArrayList[nums.length+1];//构建桶,桶的下标代表数字出现的频率
for(int key:map.keySet){
int freqence=map.get(key);
if(bucket[frequence]==null){
bucket[frequence]=new ArrayList<>();
}
bucket[frequence].add(key);
}
List<Integer>res=new ArrayList<>();
for(int i=bucket.length-1;i>=0&&res.size()<k;i--){
if(bucket[i]==null)
continue;
if(bucket[i].size<=k-res.size())
res.addAll(bucket[i]);
else
res.addAll(bucket[i].subList(0.k-res.size()));
}
return res;
}
标签:arr,nums,int,桶子,排序,public 来源: https://www.cnblogs.com/yjxyy/p/11104318.html