zoukankan      html  css  js  c++  java
  • 排序---桶排序

    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;
    }
    
  • 相关阅读:
    二进制,八进制,十进制,十六进制之间的转换
    Ajax
    JSP
    事务
    BDUtils
    LG. 1003 铺地毯
    Educational Codeforces Round 25
    POJ.3268 Silver Cow Party (Dijkstra)
    POJ.1797 Heavy Transportation (Dijkstra变形)
    POJ. 2253 Frogger (Dijkstra )
  • 原文地址:https://www.cnblogs.com/yjxyy/p/11104318.html
Copyright © 2011-2022 走看看