关于排序以及对其测试与复杂度分析

2019-04-02  本文已影响0人  墨小翼
package paixu;

public class BubbleSort {


    public static void bubblesort(int []array){
        int b=0;
        for (int i  = array.length-1;i>=0; i --) {
            for(int j=0;j< i;j++){
                if(array[j]>array[j+1]){
                    swap(array,j,j+1);
                }
            }

        }
    }
    public static void swap(int[]arr,int a,int b)
      //注意要数组传进交换函数来
    {
        int temp =arr[a];
        arr[a]=arr[b];
        arr[b]=temp;

    }
    public static void main(String[] args) {
        int []array1={1,2,3,6,3,5};

        bubblesort(array1);
        for (int i = 0; i < array1.length; i++) {

            System.out.println(array1[i]);

        }
    }
}

2.选择排序

与之思想类似,指针指向初始位置,每次循环把最小的数放在指针位置,然后指针向后移动1位。
public class SelectSort {

    public static void sort(int []arr){
        if (arr.length<2||arr==null)return;
        for (int i = 0; i < arr.length-1; i++) {
            int min=i;
            for (int j=i+1;j<arr.length;j++){
                if(arr[j]<arr[min])min=j;
                }
            swap(arr,i,min);
            }
        }

    public static void swap(int[] arr,int a,int b){
        int temp=arr[a];
        arr[a]=arr[b];
        arr[b]=temp;
    }

    public static void main(String[] args){
        int []array={1,2,1,6,3,4,2};
        sort(array);
        for (int i = 0; i < array.length; i++) {
            System.out.println(array[i]);
        }
    }
}

3.插入排序
插入排序类似于整理扑克牌,基本操作是将一个记录插入到已经排好序的有序数列中,从而得到一个有序但记录数加一的有序数列。


public class InsertSort {
  public static void sort(int []arr){
        if (arr.length<2||arr==null)return;
        for (int i = 1; i < arr.length; i++) {
            for (int j=i-1;j>=0;j--){
                if(arr[j]>arr[j+1]){
                    swap(arr,j,j+1);
                }
            }
        }
    }
    public static void swap(int[] arr,int a,int b){
        int temp=0;
        temp=arr[a];
        arr[a]=arr[b];
        arr[b]=temp;
    }

    public static void main(String[] args){
        int []array={1,2,1,6,3,4,2};
        sort(array);
        for (int i = 0; i < array.length; i++) {
            System.out.println(array[i]);
        }
    }
}

1.冒泡排序
第一次冒泡循环n次,然后然后每次冒泡比之前循环次数-1(因为指针向前移动了一位)
n+n-1+n-2+....+1=((1+n)n)1/2=1/2n+1/2n^2
T(1/2n+1/2n^2)= O(n^2)
2.选择排序同理
3.插入排序每次插入比较的过程都是和指针位置前面的元素依次比较,
即:
0+1+2+...+n-1+n=((1+n)n)
1/2=1/2n+1/2n^2
T(1/2n+1/2n2)=O(n2)

稳定性是指把排序后相同的元素的位次同排序前没有改变
那稳定了有什么好处呢?
我们来想一个工作场景,给你一个表格上面是面试的人基本信息有姓名,年龄,毕业学校。我先通过其毕业学校的排名对这个列表排序,然后在通过年龄进行排序。这样如果排序算法稳定,之前通过学校排名进行的排序的结果 ,就会在年龄相同的人中体现出来。
显而易见冒泡排序和插入排序是稳定的,而选择排序是不稳定的,是因为选择排序的交换过程可能会把第一位次的元素换到第二位次。
举个例子
序列5 8 5 2 9, 这个在执行选择排序的时候,第一遍,肯定会将array[0]=5,交换到2所在的位置,也就是 2 8 5 5 9,那么很显然,之后的排序我们就会发现,array[2]中的5会出现在原先的array[0]之前,所以选择排序不是一个稳定的排序

import java.lang.reflect.Array;
import java.util.Arrays;

public class Logarithm {
    public static void TestMethod(int []arr){
        if (arr.length<2||arr==null)return;
                for (int i = 1; i < arr.length; i++) {
                    for (int j=i-1;j>=0;j--){
                        if(arr[j]>arr[j+1]){
                            swap(arr,j,j+1);
                        }
                    }
                }
            }
    public static int [] GenerateRandeoArray(int size ,int value){
        int []arr= new int[(int)((size+1)*Math.random())];
        for (int i = 0; i < arr.length; i++) {
            arr[i]=((int) (Math.random() * (value + 1)) -(int)(Math.random()*value));
        }
        return arr;
    }
    //(value+1)*random()一定比value+1小,强制转换为int 则其范围为【0~value】了
    public static void AbsoultRightMethod(int []arr){
        Arrays.sort(arr);
    }
    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;
    }
    public static boolean IsEqual(int[]arr1,int []arr2){
        if (arr1==null&&arr2!=null)return false;
        if (arr2==null&&arr1!=null)return false;
        if (arr1==null&&arr2==null)return true;
        for (int i = 0; i < arr1.length; i++) {
            if(arr1[i]!=arr2[i])return false;
        }return true;

    }
    public static void swap(int[] arr,int a,int b){
        int temp=0;
        temp=arr[a];
        arr[a]=arr[b];
        arr[b]=temp;
    }

    public static void main(String[] args) {
            boolean success=true;
            int testtime=1;
        for (int i = 0; i < testtime; i++) {
            int[] array1=GenerateRandeoArray(100,20);
            int[]array2=CopyArray(array1);
            AbsoultRightMethod(array2);
            TestMethod(array1);
            if(!IsEqual(array1,array2)){
                success=false;
                break;
            }
            for (int i1 = 0; i1 < array1.length; i1++) {
                System.out.print(array1[i1]);
            }
            System.out.println();
            for (int i2 = 0; i2 < array2.length; i2++) {
                System.out.print(array2[i2]);
            }
            System.out.println();


        } System.out.println(success?"yes":"no");

    }
}

关于二分归并排序


public class Stack {
    public static int method1(){
        method2();
        return 0;
    }
    public static int  method2(){
        method3();
        return 0;
    }
    public static int  method3(){
        method4();
        return 0;
    }
    public static int  method4(){
       return 0;
    }
   
}

调用method1的时候method1以及其参数进栈,method1调method2的时候method2进栈......直到method4进栈。
然后method4执行完毕后会被弹出,这时method3继续执行,即执行调用了method4后的return 0;语句,然后将method3弹出.......直到所有函数都弹出,程序结束。
2.进行递归调用时也是这个道理,递归函数调用自己,把此时这个函数的个哥参数封存到栈底,然后它的子递归函数进栈,子递归函数调用自己的子函数...直到到达递归出口,即最顶端的子函数弹出,在其下面封存的函数被激活,执行,弹出,再到下一个函数激活......直到整个程序结束。

3.二分归并函数
前面提到的基本排序函数都是要一个数与剩下的数都比个遍,而二分的思想是我能不能把整体分成一半,在一半中进行比较,都比较完后我再把他们一次的整理下就好了。然后对于每个被分成一半的数我把他们看成一个整体再继续划分。这样我比较的次数就大大减少了。
这是加入了对数器测试的代码

import java.lang.reflect.Array;
import java.util.Arrays;

public class Logarithm {

    public static int merge(int []arr ,int l,int r){
        if(l==r)return 0;
        int mid =l+((r-l)>>1);
        return merge(arr,l,mid)+merge(arr,mid+1,r)+mergesort(arr,l,mid,r);
    }
    public static int mergesort(int []arr,int l,int m,int r){
        int []help=new int [r-l+1];
        int i=0;
        int p1=l;
        int p2=m+1;
        //int res=0;
        while(p1<=m&&p2<=r){
            //  res+=arr[p1]<arr[p2]?arr[p1]*(r-p2+1):0;
            help[i++]=arr[p1]>arr[p2]?arr[p2++]:arr[p1++];
        }
        while(p1<=m){
            help[i++]=arr[p1++];
        }

        while(p2<=r){
            help[i++]=arr[p2++];
        }
        for ( i = 0; i < help.length; i++) {
            arr[l+i]=help[i];
        }
        return 0;


    }
    public static int TestMethod(int []arr){
   
        if (arr == null || arr.length < 2) {
            return 0;
        }
        return merge(arr, 0, arr.length - 1);

    }
    public static int [] GenerateRandeoArray(int size ,int value){
        int []arr= new int[(int)((size+1)*Math.random())];
        for (int i = 0; i < arr.length; i++) {
            arr[i]=((int) (Math.random() * (value + 1)) -(int)(Math.random()*value));
        }
        return arr;
    }
    //(value+1)*random()一定比value+1小,强制转换为int 则其范围为【0~value】了
    public static void AbsoultRightMethod(int []arr){
        Arrays.sort(arr);
    }
    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;
    }
    public static boolean IsEqual(int[]arr1,int []arr2){
        if (arr1==null&&arr2!=null)return false;
        if (arr2==null&&arr1!=null)return false;
        if (arr1==null&&arr2==null)return true;
        for (int i = 0; i < arr1.length; i++) {
            if(arr1[i]!=arr2[i])return false;
        }return true;

    }
    public static void swap(int[] arr,int a,int b){
        int temp=0;
        temp=arr[a];
        arr[a]=arr[b];
        arr[b]=temp;
    }

    public static void main(String[] args) {
            boolean success=true;
            int testtime=100;
        for (int i = 0; i < testtime; i++) {
            int[] array1=GenerateRandeoArray(100,20);
            int[]array2=CopyArray(array1);
            AbsoultRightMethod(array2);
            TestMethod(array1);
            if(!IsEqual(array1,array2)){
                success=false;
                break;
            }
            for (int i1 = 0; i1 < array1.length; i1++) {
                System.out.print(array1[i1]);
            }
            System.out.println();
            for (int i2 = 0; i2 < array2.length; i2++) {
                System.out.print(array2[i2]);
            }
            System.out.println();


        } System.out.println(success?"yes":"no");

    }
}

4.关于递归问题的复杂度分析
这里引入一个计算递归问题复杂度的公式,有兴趣的朋友可以去自行证明这里证明就不再多提。
master公式的使用
T(N) = a*T(N/b) + O(N^d)
a为一次递归调用分出子问题的个数
b为每个子问题的数据量
c为普通逻辑语句的个数

  1. log(b,a) > d -> 复杂度为O(N^log(b,a))
  2. log(b,a) = d -> 复杂度为O(N^d * logN)
  3. log(b,a) < d -> 复杂度为O(N^d)
    那么二分归并排序的Tn=1/2T(N/2)+O(N)
    所以起时间复杂度为N*log(N)
    好了接下来我们用这种思想试着解决一个问题
小和问题

在一个数组中,每一个数左边比当前数小的数累加起来,叫做这个数组的小和。求一个数组的小和。

例子:
[1,3,4,2,5]
1左边比1小的数,没有;
3左边比3小的数,1;
4左边比4小的数,1、3;
2左边比2小的数,1;
5左边比5小的数,1、3、4、2;
所以小和为1+1+3+1+1+3+4+2=16
最简单的想法是写个双重循环把它依次的遍历

    public static int comparator(int[] arr) {
        if (arr == null || arr.length < 2) {
            return 0;
        }
        int res = 0;
        for (int i = 1; i < arr.length; i++) {
            for (int j = 0; j < i; j++) {
                res += arr[j] < arr[i] ? arr[j] : 0;
            }
        }
        return res;
    }

但再想想呢 有没有更紧单些的复杂度更低的方法呢
我们之前 在分析二分归并函数的时候 就写到当一个东西从整个的循环遍历它来进行交换的时候,这样做是很低效的。而我们用二分的思想进行划分的话可以复杂度从O(n^2)降到O(n*logn)。而对于这个问题可以这样想吗?
仔细想过程会发现 每次划分都是有一左一右的,而且归并的时候会有左右两边大小的比较,那么我们在每次比较的时候用一个变量记下左边小的情况 然后进行累加,得出结果。

public class Code_SmallSum {

    public static int smallSum(int[] arr) {
        if (arr == null || arr.length < 2) {
            return 0;
        }
        return mergeSort(arr, 0, arr.length - 1);
    }

    public static int mergeSort(int[] arr, int l, int r) {
        if (l == r) {
            return 0;
        }
        int mid = l + ((r - l) >> 1);
        return mergeSort(arr, l, mid) + mergeSort(arr, mid + 1, r) + merge(arr, l, mid, r);
    }

    public static int merge(int[] arr, int l, int m, int r) {
        int[] help = new int[r - l + 1];
        int i = 0;
        int p1 = l;
        int p2 = m + 1;
        int res = 0;
        while (p1 <= m && p2 <= r) {
            res += arr[p1] < arr[p2] ? (r - p2 + 1) * arr[p1] : 0;
            help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
        }
        while (p1 <= m) {
            help[i++] = arr[p1++];
        }
        while (p2 <= r) {
            help[i++] = arr[p2++];
        }
        for (i = 0; i < help.length; i++) {
            arr[l + i] = help[i];
        }
        return res;
    }

    // for test
    public static int comparator(int[] arr) {
        if (arr == null || arr.length < 2) {
            return 0;
        }
        int res = 0;
        for (int i = 1; i < arr.length; i++) {
            for (int j = 0; j < i; j++) {
                res += arr[j] < arr[i] ? arr[j] : 0;
            }
        }
        return res;
    }

    // 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()) - (int) (maxValue * 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 = 100;
        boolean succeed = true;
        for (int i = 0; i < testTime; i++) {
            int[] arr1 = generateRandomArray(maxSize, maxValue);
            int[] arr2 = copyArray(arr1);
            if (smallSum(arr1) != comparator(arr2)) {
                succeed = false;
                printArray(arr1);
                printArray(arr2);
                break;
            }https://www.keybr.com/
        }
        System.out.println(succeed ? "Nice!" : "Fucking fucked!");
    }

}

快速排序

给定一个数组arr,和一个数num,请把小于num的数放在数组的
左边,等于num的数放在数组的中间,大于num的数放在数组的
右边。
要求额外空间复杂度O(1),时间复杂度O(N)


不言而喻

2.思考过程

很简单 我们通过设置三个指针 分别指向数组外的两端
以代表我们规划大于num和小于num的区域
再有一个指针指向数组第一个元素进行遍历
如果不等于num就与划分区域附近的元素(或左或右)进行交换
等于的话就跳过

3.实现过程中遇到的麻烦

1最开始习惯性的用了for去做便利指针的移动,但发现指针的移动是有多种条件的 不适合for
2对从后面还来的数还需要判断,通过指针的不动解决
3.通过限定i++的条件 即只有和自己或者相等的元素交换才能++ 来保证区域的划分

public class flag {
    public static void Flag(int[] arr, int num) {
        int small = -1;
        int big = arr.length;
        int i = 0;
        while (i < big)//
        {//通过指针的不动来控制下一次循环依旧从该位置进行判定

            if (arr[i] <num) {
                swap(arr, i++, ++small);//对换过来的数已经进行了限定,
//即限定了小于区域后面得数只可能是等于区域的数或者我自己,
//如果是大于区域的数就会重新考虑

            } else if (arr[i] > num) {
                swap(arr, --big, i);//通过指针的停留重新考录换过来的数
            } else {
                i++;
            }
        }
    }

    public static void swap(int[] arr, int a, int b) {
        int temp = arr[a];
        arr[a] = arr[b];
        arr[b] = temp;
    }

    public static void main(String[] args) {
        int a[] = {1, 3, 2, 6, 6, 236};
        Flag(a,5);
        for (int i = 0; i < a.length; i++) {
            System.out.print(a[i]);
        }

    }

}

快速排序中就是通过运用荷兰国旗问题不断地把数组化为
一边<num一边>num中间等于的部分不动支队两边递归
如果说二分归并排序运用了递归溯洄的时候那么快排则是运用了递归函数不断地向下划分的过程每次向下递归时我都把你先分成一半比一个数小一般比一个数大。


public class QuickSort {
public static int [] partion(int arr[],int l,int r ){
    int small=l-1;
    int big=r+1;
    while(l<r){
        if (arr[l]<arr[r-1]){
            swap(arr,++small,l++);
        }
        else if (arr[l]>arr[r-1]){
            swap(arr,--big,l);
        }
        else l++;
    }
    int []help=new int [2];
    help[0]=small;
    help[1]=big;
    return help;
}
public static void quick (int []arr,int l,int r){
    int []help=partion(arr, l,r);
    if(l>=r)return;
    quick(arr,l,help[0]+1);//注意这里help返回的是big和small,
    quick(arr,help[1]-1,r);
}
    public static void swap(int []arr,int a,int b){
    int temp =arr[a];
    arr[a]=arr[b];
    arr[b]=temp;

    }

    public static void main(String[] args) {
     int []a={1,3,9,1,4,3,5,3};
     quick(a,0,a.length-1);
        for (int i = 0; i < a.length; i++) {
            System.out.println(a[i]);
        }

    }

}

4.这里要提的一句是程序的运行是与数据有关系的,每次进行划分的时候我们都是按照最后一个数进行划分的,那么问题来了。如果数据是2,3,4,5,6,1呢 我们需要一直从头遍历,怎么解决这样的问题呢?
很简单在划分前把最后一个数与前面随机一个数交换就好了。
代码如下

public class QuickSort1 {
public static int []partion (int []arr,int l,int r){
    int small=l-1;
    int big=r+1;//小错

    while(l<big){//不思考就写习惯性的出写了l<r
         if(arr[l]<arr[r]){
             swap(arr,++small,l++);
         }
         else if ((arr[l])>arr[r]){
             swap(arr,--big,l);
         }
         else{
             l++;
         }
     }
    int []help=new int [2];
    help[0]=small;
    help[1]=big;
    return help;
}
public static void QuickSort(int []arr,int l,int r){
    if(l>=r)return;
    swap(arr,l+(int)((r-l+1)*Math.random()),r);//从零开始一直到r-l的r-l+1个数
    int []help=partion(arr,l,r);
    QuickSort(arr,l,help[0]-1);//小错
    QuickSort(arr,help[1]+1,r);

}
public static void swap(int []arr,int i,int j){
    int temp=arr[i];
    arr[i]=arr[j];
    arr[j]=temp;

}

    public static void main(String[] args) {
        int []a={1,2,3,1};
        QuickSort(a,0,a.length-1);
        for (int i = 0; i < a.length; i++) {
            System.out.println(a[i]);
        }
    }

}

5.这里分析一下其复杂度

  1. 在说堆排的时候我们先了解一下堆这种结构吧堆其实是就是数组。只是我们把数组脑补成一个完全二叉树。

2.完全二叉树包括满二叉树。

3.根节点为n的话,子节点为2*n+1

怎么把数组生成大根堆
想法是这样的
从最开始的跟位置不断和上一根结点比较如果比根节点大就交换指针放到根节点位置不断循环直到 堆的顶部

代码如下:

package paixu;

public class Heap_Big_Initialise {
public static void HeapIntialise(int[]arr){
    for (int i = 0; i < arr.length; i++) {
        HeapInsert(arr,i);
    }
}
public static void HeapInsert(int[] arr,int i){
    while (arr[i]>arr[(i-1)/2]){
        swap(arr,i,(i-1)/2);
        i=(i-1)/2;
    }
}
public static void swap(int[]arr,int i,int j){
    int temp=arr[i];
    arr[i]=arr[j];
    arr[j]=temp;


}
public static void main(String[] args) {
   int arr[]={1,2,3,5,4};
   HeapIntialise(arr);
   for (int i = 0; i < arr.length; i++) {
        System.out.println(arr[i]);
    }
    }
}

那怎么通过堆结构进行排序呢?
这就引入了heapify的概念了,即使删除堆顶元素的堆再次成为堆。
首先小根堆堆顶元素是一定为最小的,我们用一个数组不断得保留堆顶元素的值,然后把最底下的一个叶子结点放在堆顶,让它不断地向下和比它小的子节点交换。


代码如下
package paixu;

public class heap {

    public static void heapsort(int[]arr){
        //建堆
        for (int i = 0; i < arr.length; i++) {
            heapinsert(arr,i);
        }

        int size=arr.length-1;
       while (size>0) {
            swap(arr, 0, size--);
           heapfy(arr, size);

        }
    }
    //建大根堆用
    public static void heapinsert(int[] arr,int i){
        while (arr[i]>arr[(i-1)/2]){
            swap(arr,i,(i-1)/2);
            i=(i-1)/2;
        }
    }
    //从上往下不断比较的方法
    public static void heapfy(int []arr,int size){
        int index=0;
        int left=index*2+1;
        while(left<size){
            int large=(arr[left]>arr[left+1])&&left+1<=size?left:left+1;
            large=arr[index]>arr[large]?index:large;

            if(index==large){
                break;
            }

                swap(arr,large,index);
                index=large;
                left=index*2+1;

        }
    }
    //交换函数

    public static void swap(int[]arr,int i,int j){
        int temp=arr[i];
        arr[i]=arr[j];
        arr[j]=temp;


    }
    public static void main(String[] args) {
        int arr[]={1,3,2,6};
        heapsort(arr);
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }

      }
}

P.S.
对于二分归并排序我只要保证归并的时候左边小于等于右边就先把左边归并,就可以保证二分归并排序的稳定性。
对于快排,是可以实现稳定排序的但是已经是论文级别的难度了,这里不说了。

关于工程排序算法

IMG_0219(20190408-164936).jpg

桶排序

个人感觉桶排序是最笨拙也是最有灵魂的排序了
1.它是不基于比较的排序,时间复杂度可达到O(n)
2.它的基本想法是,比如说我对1~6六个数进行进行排序,我就申请六个数的辅助数组。然后待比较元素和数组下标一致的话该下标下的计数器++,
然后我按计数器个数一次输出辅助数组下表就好了。
3.当然这样会有数据范围与数据量的问题,数据量很大的话我就只对你数据的前几位进行桶排序,然后再对每个桶里的数据的前几位排序进行桶排序,可见这并不具有普适性。
4.但桶排序这种思想有时候能做很取巧的事。

那么问题来了

我为什么要有把差值分成n份呢即我为何要准备n+1个桶呢,重点来了由于鸽巢原理 必有一个桶是空的 这就保证了我的max是不可能在一个桶里的两个数的差值取到的。而只可能是两个及以上(中间有空桶)的桶之间取到的


具体关于n分的详细分析

代码

package basic_class_01;
import java.util.Arrays;


public class 桶排序 {

        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);
                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) {
            return (int) ((num - min) * len / (max - min));
        }

        // for test
        public static int comparator(int[] nums) {
            if (nums == null || nums.length < 2) {
                return 0;
            }
            Arrays.sort(nums);
            int gap = Integer.MIN_VALUE;
            for (int i = 1; i < nums.length; i++) {
                gap = Math.max(nums[i] - nums[i - 1], gap);
            }
            return gap;
        }


    public static void main(String[] args) {
        int []a={1,4};
        System.out.println(maxGap(a));
}

}
上一篇下一篇

猜你喜欢

热点阅读