• 桶排序


    首先讨论的问题:给定一个数组,求如果排序后,相邻两数的最大值,要求时间复杂度 O(n)?

    :数组长度N,设计一个桶,数量为(N+1)个桶,数组最小值放进第一个桶,数组最大值放进最后一个桶,每一个桶都要包含minmax,这两个边界值。所以中间一定存在一个空桶,那么就可以得到一个结论:桶内之间绝对不会存在最大差值,最大差值就一定在桶与桶的边界值之间。从第二个桶开始遍历,用这个桶的min减去前一个非空桶max得到差值,那么整个数组相邻的最大差值一定在这里面。

    #include <stdio.h>
     
    //根据要入桶的数和最大最小值得到对应桶编号
    int getBucketId(int num,int bucketsNum,int min,int max){
        return (num - min) * bucketsNum / (max - min);
    }
     
    int max(int a, int b){
        return a > b ? a : b;
    }
     
    int min(int a, int b){
        return a < b ? a : b;
    }
     
    int getMaxGap(int arr[], int length) {
        if (arr == NULL || length < 2) {
            return -1;
        }
        int maxValue = -999999, minValue = 999999;
        int i;
        //找出最大最小值
        for (i = 0; i < length; ++i) {
            maxValue = max(maxValue, arr[i]);
            minValue = min(minValue, arr[i]);
        }
        //记录每个桶的最大最小值以及是否有数,初始时每个桶都没数
        int maxs[length + 1], mins[length + 1];
        bool hasNum[length + 1];
        for (i = 0; i < length + 1; i++) {   
            hasNum[i] = false;
        }
        //put maxValue into the last bucket
        mins[length] = maxs[length] = maxValue;
        hasNum[length] = true;
     
        //iterate the arr
        int bid; //bucket id
        for (i = 0; i < length; i++) {
            if (arr[i] != maxValue) {
                bid = getBucketId(arr[i], length + 1, minValue, maxValue);
                  //如果桶里没数,则该数入桶后,最大最小值都是它,否则更新最大最小值
                mins[bid] = !hasNum[bid] ? arr[i] : arr[i] < mins[bid] ? arr[i] : mins[bid];
                maxs[bid] = !hasNum[bid] ? arr[i] : arr[i] > maxs[bid] ? arr[i] : maxs[bid];
                hasNum[bid] = true;
            }
        }
     
        //find the max gap between two nonEmpty buckets
        int res = 0, j = 0;
        for (i = 0; i < length; ++i) {
            j = i + 1;//the next nonEmtpy bucket id
            while (!hasNum[j]) {//the last bucket must has number
                j++;
            }
            res = max(res, (mins[j] - maxs[i]));
        }
     
        return res;
    }
     
    int main(){
        int arr[] = {13, 41, 67, 26, 55, 99, 2, 82, 39, 100};
        printf("%d", getMaxGap(arr, 9));    //17
        return 0;
    }

    理解了上述代码的话,桶排序就很简单了,就是计数排序,统计一个数出现了多少次,然后重新打印会数组。但是局限于要排序的数组max值很小。否则数组开销代价太大。桶排序是非比较的,是统计的。

    package 左神_算法;
    import java.util.Arrays;
    
    public class BucketSort {
    	/**
    	 * 桶排序
    	 * 1,非基于比较的排序,与被排序的样本的实际数据状况很有关系,所
    	  	以实际中并不经常使用
    	 * 2,时间复杂度O(N),额外空间复杂度O(N)
    	 * 3,稳定的排序
    	 *
    	 */
    	 
    		// only for 0~200 value,计数排序
    		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];  // 定义一个可以容纳数组里面的max+1个数
    			for (int i = 0; i < arr.length; i++) {  // 把arr的值映射进数组里面,记录有多少个
    				bucket[arr[i]]++;
    			}
    			int i = 0;
    			for (int j = 0; j < bucket.length; j++) {  //把桶里面的值,重新输入到arr中
    				while (bucket[j]-- > 0) {
    					arr[i++] = j;
    				}
    			}
    		}
    	 
    		// for test
    		public static void comparator(int[] arr) {
    			Arrays.sort(arr);
    		}
    	 
    		// for test
    		public static int[] generateRandomArray(int maxSize, int maxValue) {
    			int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
    			for (int i = 0; i < arr.length; i++) {
    				arr[i] = (int) ((maxValue + 1) * Math.random());
    			}
    			return arr;
    		}
    	 
    		// for test
    		public static int[] copyArray(int[] arr) {
    			if (arr == null) {
    				return null;
    			}
    			int[] res = new int[arr.length];
    			for (int i = 0; i < arr.length; i++) {
    				res[i] = arr[i];
    			}
    			return res;
    		}
    	 
    		// for test
    		public static boolean isEqual(int[] arr1, int[] arr2) {
    			if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
    				return false;
    			}
    			if (arr1 == null && arr2 == null) {
    				return true;
    			}
    			if (arr1.length != arr2.length) {
    				return false;
    			}
    			for (int i = 0; i < arr1.length; i++) {
    				if (arr1[i] != arr2[i]) {
    					return false;
    				}
    			}
    			return true;
    		}
    	 
    		// for test
    		public static void printArray(int[] arr) {
    			if (arr == null) {
    				return;
    			}
    			for (int i = 0; i < arr.length; i++) {
    				System.out.print(arr[i] + " ");
    			}
    			System.out.println();
    		}
    	 
    		// for test
    		public static void main(String[] args) {
    			int testTime = 500000;
    			int maxSize = 100;
    			int maxValue = 150;
    			boolean succeed = true;
    			for (int i = 0; i < testTime; i++) {
    				int[] arr1 = generateRandomArray(maxSize, maxValue);
    				int[] arr2 = copyArray(arr1);
    				bucketSort(arr1);
    				comparator(arr2);
    				if (!isEqual(arr1, arr2)) {
    					succeed = false;
    					printArray(arr1);
    					printArray(arr2);
    					break;
    				}
    			}
    			System.out.println(succeed ? "Nice!" : "Fucking fucked!");
    	 
    			int[] arr = generateRandomArray(maxSize, maxValue);
    			printArray(arr);
    			bucketSort(arr);
    			printArray(arr);
    	 
    		}
    	
    
    }
    
  • 相关阅读:
    UWP Composition API
    UWP VirtualizedVariableSizedGridView 支持可虚拟化可变大小Item的View(二)
    UWP VirtualizedVariableSizedGridView 支持可虚拟化可变大小Item的View(一)
    UWP 图片剪切旋转工具
    整理UWP中网络和设备信息获取的帮助类,需要的拿走。
    UWP 设备分辨率
    UWP webview 键盘bug,回退页面,键盘会弹一下。
    UWP 解决Webview在Pivot里面无法左右滑动的问题
    ngnix https
    nginx www解析失败问题解决
  • 原文地址:https://www.cnblogs.com/horken/p/10706136.html
Copyright © 2020-2023  润新知