【JAVA】数据结构——堆的排序及相关面试题

目录

1.堆的排序

2.直接插入排序

3.希尔排序(缩小增量法)

4.选择排序

5.堆排序

6.冒泡排序

7. 快速排序

7.1未优化快速排序:递归完成

7.2 优化快速排序: (三数取中) 非递归分治 --> 不会堆溢出 

7.3  非递归  快速排序:  

8.   归并排序 

8.1 递归实现 归并排序 

8.2  归并排序   ---->非递归排序 

9. 合并两个有序数组  

10.    计数排序:  

 11.topK问题

面试题1:查找和最小的 K 对数字

11.测试数据运行时间


1.大小堆的创建、如何放元素、获取队头元素:

【JAVA】数据结构——优先级队列(堆的应用)

基于比较的排序方法:

排序方法最好平均最坏空间复杂度稳定性
冒泡排序O(n)O(n^2)O(n^2)O(1)稳定
插入排序O(n)O(n^2)O(n^2)O(1)稳定
选择排序O(n^2)O(n^2)O(n^2)O(1)不稳定
希尔排序O(n)O(n^1.3)O(n^1.5)O(1)不稳定
堆排序O(n * log(n))O(n * log(n))O(n * log(n))O(1) 不稳定
快速排序 O(n * log(n))O(n * log(n))O(n^2)O(log(n)) ~ O(n) 不稳定
归并排序  O(n * log(n))O(n * log(n))O(n * log(n))O(n)稳定

稳定的排序方式:冒泡、直接插入、归并排序

冒泡、选择、直接插入排序都是比较简单的排序,

1.堆的排序

升序,则创建大根堆


/*从小到大排序:
1. 调整为大根堆
2. 0下标和最后一个未排序的元素进行交换
3. end-- 
* */
    public void heapSort() {
        int end = usedSize-1;
        while (end > 0) {
            int tmp = elem[0];
            elem[0] = elem[end];
            elem[end] = tmp;
            shiftDown(0,end);  //向下调整
            end--;
        }
    }

2.直接插入排序

时间复杂度: O(N^2) --》最好的情况O(N):数据有序
空间复杂度: O(1)
稳定性: 稳定
若一个本身就不稳定的排序,是不会变成稳定的排序的


public class testSorts {

    public static void insertSort(int[] array) {
        for (int i = 1; i < array.length; i++) {
            int tmp = array[i]; //开辟一块内存tmp存放从第二个元素开始的array[i]元素
            int j = i-1;  //j始终在i的前一个位置
            for (; j >= 0 ; j--) {
                if (array[j] > tmp) { //如果j下标大于tmp的值,则将array[j]往后移(升序)
                    array[j+1] = array[j];  //也即是ij对应元素互换
                }else {  //不大于(<=)就不移动,默认是升序排列,退出此步操作
//                    array[j+1] = tmp;
                    break; //只要j回退到比tmp小的元素就结束这次比较
                }
            }//j为负数时候
            //j回退到小于0的地方
            array[j+1] = tmp;
        }
    }

3.希尔排序(缩小增量法)

分组,组内是直接排序(是对直接插入排序的优化)

希尔排序法的基本思想是:先选定一个整数,把待排序文件中所有记录分成个组,所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后,重复上述分组和排序的工作。当到达=1时,所有记录在统一组内排好序。
1. 希尔排序是对直接插入排序的优化。
2. 当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。

 时间复杂度【和增量有关系】:O(N^1.3到N^1.5)最好和最坏 --》最好的情况O(N):数据有序
 空间复杂度:O(1)
 稳定性:不稳定
 交换过程中若发生跳跃式交换,则是不稳定的 


// gap:组数         array:待排数列
    public static void shell(int[] array,int gap) {  //此函数shell也即是直接插入排序方法
        for (int i = gap; i < array.length; i++) { //i从下标为gap的值开始
            int tmp = array[i];
            int j = i-gap;
            for (; j >=0; j -= gap) {
                if (array[j] > tmp) { //tmp是i处的值,j在左边,而array[j]值更大,说明不是有序的,需要更换位置
                    array[j+gap] = array[j]; //j+gap也即是i,此处为交换ij对应元素
                }else {   //如果值符合要求,则位置不变动,退出此次循环即可,继续下一步的循环:i+1
                    break;
                }
            }
            array[j+gap] = tmp;  //j < 0,  tmp不变化,也即是将i放回原位置
        }
    }

    public static void shellSort(int[] array) {
        int gap = array.length;
        while (gap > 1) {      //进行分组,预排序
            shell(array,gap);
            gap /=2;
        }
        shell(array,1); //保证最后是一组

    }

4.选择排序

保持第一个元素不动,后续元素依次与此进行大小比较,后面值小的话进行位置交换

时间复杂度【和增量有关系】: O(N^2)  对数据不敏感
空间复杂度:  O(1)
稳定性: 不稳定

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

    public static void selectSort1(int[] array) {
        for (int i = 0; i < array.length; i++) {
            for (int j = i + 1; j < array.length; j++) {
                if(array[i] > array[j]) {   //升序排列 降序排列:array[i] < array[j]
                    swap(array,i,j);
                }
            }
        }
    }

//优化选择排序
    public static void selectSort(int[] array) {
        for (int i = 0; i < array.length; i++) {
            int minIndex = i;
            for (int j = i + 1; j < array.length; j++) {
                if (array[j] < array[minIndex]) {
                    minIndex = j;
                }
            }
            swap(array,i,minIndex);
        }
    }


5.堆排序

升序(从小到大):建立大根堆

基本原理:选择排序,但不使用遍历的方式,而是通过堆来选择查找无序区间的最大的数

 时间复杂度:O(N*log2(N))
 空间复杂度: O(1)
稳定性: 不稳定

解析:

1.先创建大根堆createHeap
2.0下标和end下标交换
3.继续调整当前堆为大根堆shiftDown
4.end--,继续交换

    public static void heapSort(int[] array) { //堆排序
        createHeap(array); //首先创建大根堆---->0下标和最后一个下标end(array.leng-1)进行位置交换
        int end = array.length-1;  //end为最后一个元素下标
        while (end > 0) { //循环条件:end 》 0,当end走到0下标时完成交换
            swap(array,0,end); //进行交换,交换结束之后调整为大根堆
            shiftDown(array,0,end); //调整为大根堆之后,根节点依旧是除开end之外的最大值
            end--; //此时再继续进行交换(end和0),继续循环
        }
    }
    public static void createHeap(int[] array) {
        //child = array.length-1;
        //大根堆parent往后走,最初只会知道最后一个孩子的下标array.length-1,由此可得对应parent
        for (int parent = (array.length-1-1)/2; parent >= 0 ; parent--) {
            shiftDown(array,parent,array.length);  //大根堆:向下调整,
        }
    }
    public static void shiftDown(int[] array,int parent,int len) {
        int child = 2*parent+1;   //左孩子
        while (child < len) {  //循环条件:孩子child下标在数组长度范围内
            //child+1 < len说明至少有一个右孩子--》array[child] < array[child+1]表明右孩子更大,
            if (child+1 < len && array[child] < array[child+1]) { //此处child+1是右孩子,没有超过数组长度len,且左孩子<右孩子
                child++; //变为最后一个孩子,且右孩子大于左孩子
            }
            //child下标是左右孩子最大值的下标
            if (array[child] > array[parent]) { //如果孩子对应值>父亲节点,则进行交换(保持根(父亲)节点>孩子)
                swap(array,child,parent);
                parent = child;  //交换之后继续往后走,父亲节点走到子节点位置,而子节点继续向后走
                child = 2*parent+1;
            }else {  //孩子节点不大于父亲节点,则不用交换,退出break即可
                break;
            }
        }
    }

6.冒泡排序

在无序区间,通过相邻数的比较,将最大的数冒泡到无序区间的最后,持续这个过程,直到数组整体有序

时间复杂度】:O(N^2)
空间复杂度:O(1)
稳定性:稳定


//========================未优化冒泡排序:====================================//

    public static void bubbleSorts0(int[] array) {
        for (int i = 0; i < array.length-1; i++) {
            for (int j = 0; j < array.length-1-i; j++) { //每一次会确定一个有序值放在最后,因此,j的长度每次也会减少
                if (array[j] > array[j+1]) {
                    swap(array,j+1,j);
                }
            }
        }
    }
//========================优化冒泡排序:====================================//
//2.时间复杂度】:最坏O(N^2)  最好O(N)
    public static void bubbleSorts(int[] array) {
        for (int i = 0; i < array.length-1; i++) {
            boolean isSorted= false;
            for (int j = 0; j < array.length-1-i; j++) { //每一次会确定一个有序值放在最后,因此,j的长度每次也会减少
                if (array[j] > array[j+1]) {
                    swap(array,j+1,j);
                   isSorted = true;
                }
            }
            if (isSorted == false) {
                break;
            }
        }
    }

7. 快速排序

7.1未优化快速排序:递归完成

时间复杂度】:最坏O(N^2)  最好O(N*log2(N))
空间复杂度:O(N)
稳定性:不稳定

 解析:

1.选择基准,将第一个元素存放到tmp,从后往前找,若比tmp大,end--,继续往前寻找,不变换位置;若比tmp小的值放到第一个位置start下标处;
2.然后从start开始遍历,找>tmp的值,将其放入到end--停留的位置处
3.继续执行上述操作,继续找比基准元素tmp大或者小元素并移动位置,----》左边的值<基准,右边>基准。
4.继续将第一个元素作为基准元素,重复上述操作

//start:起始下标    end:最后一个元素下标    pivot:基准下标   
  //1.找基准元素 :
    public static int partition(int[] array, int start, int end)  {//找基准的函数
        int tmp = array[start]; // 基准找完之后从后找
        while (start < end) {
            while (start < end && array[end] >= tmp) { //比基准元素大,则不移动该元素,向前找end--
                end--;
            }
            //走完之后end下标遇到 < tmp的值
            array[start] = array[end];  //遇到的值<tmp,则将其放入start位置
            while (start < end && array[start] <= tmp) {
                start++; //array[start] 小于基准tmp元素,则不移动,继续向前遍历,start++
            }
            //当array[start] > tmp,则向后移动到 上一步的end的位置
            array[end] = array[start];
        }
        array[start] = tmp; //start 和end相遇,将tmp放到这个位置,至此/第一次循环结束,得到基准元素左边的值小于基准,右边的值大于基准,
        return start; //返回start或者end,也即是相遇的位置
    }

//找到基准元素之后,对其左右进行排序
    public static void quick0(int[] array,int left,int right) { //类似二叉树,分而治之,先找到基准,然后执行左边和右边
        if (left >= right) { //当左右相遇的时候,退出递归,直接return。
            return;
        }//退出之后继续找第一个元素作为基准
        int pivot = partition(array,left,right);//先找到基准,在分别递归左边和右边
        quick(array,left,pivot-1);
        quick(array,pivot+1,right);
    }

    public static void quickSort0(int[] array) {  //快速排序:完成对一个数组的排序
        quick(array,0, array.length-1);// 对数组array,从下标0到array.length-1进行排序--》快速排序也即是递归quick的一个过程
    }

   

7.2 优化快速排序: (三数取中) 非递归分治 --> 不会堆溢出 


时间复杂度】:最坏O(N^2)  最好O(N)
空间复杂度:O(1)
稳定性:不稳定

解析:

1.选择基准,将第一个元素存放到tmp,从后往前找,若比tmp大,end--,继续往前寻找,不变换位置;若比tmp小的值放到第一个位置start下标处;
2.然后从start开始遍历,找>tmp的值,将其放入到end--停留的位置处
3.继续执行上述操作,继续找比基准元素tmp大或者小元素并移动位置,----》左边的值<基准,右边>基准。
4.继续将第一个元素作为基准元素,重复上述操作


    private static int findMidValIndex(int[] array,int start,int end) {
        int mid = start + ((end - start) >>> 1);  // >>> 1:右移1位--》也即是除2
        if (array[start] < array[end]) {
            if (array[mid] < array[start]) {
                return start;
            } else if (array[mid] > array[end]) {
                return end;
            } else {
                return mid;
            }
        }else {
            if (array[mid] > array[start]) {
                return start;
            } else if (array[mid] < array[end]) {
                return end;
            }else {
                return mid;
            }
        }
    }

    public static void quick(int[] array,int left,int right) { //类似二叉树,分而治之,先找到基准,然后执行左边和右边
        if (left >= right) { //当左右相遇的时候,退出递归,直接return。
            return;
        }
        //1.如果区间内的数据在排序过程中,如果小于某个范围(如40),则可直接进行直接插入排序
        if (right-left+1 <=40) {
            insertSort(array);
            return;
        }
        //2.退出之后继续找中间元素作为基准(三数取中)
        int midValIndex = findMidValIndex(array,left,right);
        swap(array,left,right);

        int pivot = partition(array,left,right);//先找到基准,在分别递归左边和右边
        quick(array,left,pivot-1);
        quick(array,pivot+1,right);
    }

    public static void quickSort(int[] array) {  //快速排序:完成对一个数组的排序
        quick(array,0, array.length-1);// 对数组array,从下标0到array.length-1进行排序--》快速排序也即是递归quick的一个过程
    }



7.3  非递归  快速排序:  

解析:

1.找基准
2.借用栈 --》放入左区间下标、和右区间下标-->相对于基准的左右(四个下标值)--》前提是基准pivot左右都有俩元素
3.弹出栈顶两个元素,也即是右边区间的两个下标
4.然后再弹出的两个下标区间内找基准:第一个下标元素放入tmp,从最后一个下标往前依次与tmp比较,  当后面的值比tmp小时,则将其移动到弹出区间的第二个位置


    public static void quickSorts(int[] array) {
        Stack<Integer> stack = new Stack<>();
        int left = 0;
        int right  = array.length-1;
        int pivot = partition(array,left,right);
        if (pivot > left+1) { //说明左边有至少俩元素
            stack.push(left);  //将左边下标放入堆里
            stack.push(pivot-1);
        }
        if (pivot < right-1) { //说明右边边有至少俩元素
            stack.push(pivot+1);  //将右边下标放入堆里
            stack.push(right);
        }
        //查看栈是否为空,不为空执行以下循环:弹出两个元素作为左右下标继续找基准
        while (!stack.isEmpty()) {
            right  = stack.pop();
            left = stack.pop();
            pivot = partition(array,left,right);

            if (pivot > left+1) { //说明左边有至少俩元素
                stack.push(left);  //将左边下标放入堆里
                stack.push(pivot-1);
            }
            if (pivot < right-1) { //说明右边边有至少俩元素
                stack.push(pivot+1);  //将右边下标放入堆里
                stack.push(right);
            }
        }
    }

 //1.找基准元素 :
    public static int partition(int[] array, int start, int end)  {//找基准的函数
        int tmp = array[start]; // 基准找完之后从后找
        while (start < end) {
            while (start < end && array[end] >= tmp) { //比基准元素大,则不移动该元素,向前找end--
                end--;
            }
            //走完之后end下标遇到 < tmp的值
            array[start] = array[end];  //遇到的值<tmp,则将其放入start位置
            while (start < end && array[start] <= tmp) {
                start++; //array[start] 小于基准tmp元素,则不移动,继续向前遍历,start++
            }
            //当array[start] > tmp,则向后移动到 上一步的end的位置
            array[end] = array[start];
        }
        array[start] = tmp; //start 和end相遇,将tmp放到这个位置,至此/第一次循环结束,得到基准元素左边的值小于基准,右边的值大于基准,
        return start; //返回start或者end,也即是相遇的位置
    }

8.   归并排序 

8.1 递归实现 归并排序 

归并排序:是建立在归并操作上的一种有效的排序算法,采用分治法。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。

将两个有序表合并成一个有序表,称为二路归并。

时间复杂度】:O(N*log(N))
空间复杂度:O(N)
稳定性:稳定  若(array[s1] <= array[s2],不取等号则是不稳定的


    public static void merSort(int[] array) {  //合并有序的两个数组
        mergeSortInternal(array,0,array.length-1);
    }
    public static void mergeSortInternal(int[] array,int low,int high) {
        if (low >= high) {
            return;
        }
        int mid = low + (high-low) >>>1;  //(low+high)/2

        mergeSortInternal(array,low,mid); //左边
        mergeSortInternal(array,mid+1,high); //右边
        merge(array,low,mid,high);//合并
    }
    public static void merge(int[] array,int low,int mid,int high){  //合并两个有序数组:二路归并
        int[] array3 = new int[high-low+1];//创建一个新数组用于存放元素
        int k = 0;  //k为新数组下标
        int s1 = low;  //有序数组1
        int e1 = mid;

        int s2 = mid+1;  //有序数组2
        int e2 = high;

        while (s1 <= e1 && s2 <= e2) {
            if (array[s1] <= array[s2]) {  //比较两个有序数组第一个元素的大小,小的元素放入新数组
                array3[k++] = array[s1++];
            }else {  // 另一个数组元素小 array2[s2] < array1[s1]
                array3[k++] = array[s2++];
            }
        }
        while (s1 <= e1) {  //此时说明第一个数组还剩下数据没移动到新数组,直接将其放入到新数组即可
            array3[k++] = array[s1++];
        }
        while (s2 <= e2) {
            array3[k++] = array[s2++];
        }
        //拷贝array数组元素,放入原数组
        for (int i = 0; i < k; i++) {
            array[i+low] = array3[i];
        }
    }

8.2  归并排序   ---->非递归排序 

时间复杂度】:O(N*log(N))
空间复杂度:O(N)
稳定性:稳定  若(array[s1] <= array[s2]不取等号则是不稳定的

    //定义i下标遍历数组
    public static void merSort1(int[] array) {  //合并有序的两个数组
        int gap = 1;
        int nums = 1;
        while (gap < array.length) {
            //每次都要对数组进行遍历
            for (int i = 0; i < array.length; i +=nums*2) {
                int left = i;
                int mid = left+nums-1;
                if (mid >= array.length) { //防止越界
                    mid = array.length-1;
                }
                int right = mid+nums;
                if (right >= array.length) {
                    right = array.length-1;
                }
                merge1(array,left,mid,right);
            }
            nums *=2;
        }
    }

    public static void merge1(int[] array,int low,int mid,int high){  //合并两个有序数组
        int[] array3 = new int[high-low+1];//创建一个新数组用于存放元素
        int k = 0;
        int s1 = low;
        int e1 = mid;

        int s2 = mid+1;
        int e2 = high;

        while (s1 <= e1 && s2 <= e2) {
            if (array[s1] <= array[s2]) {
                array3[k++] = array[s1++];
            }else {  // 另一个数组元素小 array2[s2] < array1[s1]
                array3[k++] = array[s2++];
            }
        }
        while (s1 <= e1) {  //此时说明第一个数组还剩下数据没移动到新数组,直接将其放入到新数组即可
            array3[k++] = array[s1++];
        }
        while (s2 <= e2) {
            array3[k++] = array[s2++];
        }
        //拷贝array数组元素,放入原数组
        for (int i = 0; i < k; i++) {
            array[i+low] = array3[i];
        }
    }

9. 合并两个有序数组  

  解析:

1.将两个有序数组合并为一个数组:定义两个数组的起始下标-->也即是(二路归并)
2.比较两个数组第一个元素的大小,将小的元素放入到一个新的数组,有小元素的数组继续向后走
3.将其的第二个元素与另一个数组的第一个元素进行比较,小的放入新的数组而各个位置;
4.重复以上2和3步骤---》若其中一个数组走完(下标超出length-1),直接将另一个数组剩下的的元素放入新数组即可,至此完成两个数组的合并


    public static int[] mergeArray(int[] array1,int[] array2) {
        int[] array3 = new int[array1.length+array2.length];//创建一个新数组用于存放元素
        int k = 0; //新数组下标
        int s1 = 0;  //数组1起始下标
        int e1 = array1.length-1;

        int s2 = 0; //数组2起始下标
        int e2 = array2.length-1;

        while (s1 <= e1 && s2 <= e2) { // 当两个数组都在下表范围内时,比较元素大小
            if (array1[s1] <= array2[s2]) {  //数组1更小则将其让如新数组
                array3[k++] = array1[s1++];
            }else {  // 数组2元素小 array2[s2] < array1[s1]
                array3[k++] = array2[s2++];
            }
        }
        //此时已经有一个数组走完,另一个数组还剩下元素,只需将剩下的直接放入新数组即可
        while (s1 <= e1) {  //此时说明第一个数组还剩下数据没移动到新数组,直接将其放入到新数组即可
            array3[k++] = array1[s1++];
        }
        while (s2 <= e2) {
            array3[k++] = array2[s2++];
        }
        return array3;
    }

10.    计数排序:  

适用于有N个数,数据范围:0-N之间 

解析:

1.先创建一个计数数组count[]用于存放每个数组中每个元素出现的次数-->count数组范围是原数组数据的最小值到最大值
2.求数组的最大值maxval和最小值minval--->maxval-minval+1=count[]数组长度
3.count[array[i]-minval]
    当前代码不稳定  但是计数排序的本质是稳定的


    public static void countingSort(int[] array) {
        int maxVal = array[0];
        int minVal = array[0];
        for (int i = 1; i < array.length; i++) {
            if (array[i] < minVal) {
                minVal = array[i];
            }
            if (array[i] > maxVal) {
                maxVal = array[i];
            }
        }
        //此时找到了最大值和最小值
        int[] count = new int[maxVal-minVal+1]; //默认都是0
        //统计每个数据出现的次数
        for (int i = 0; i < array.length; i++) {  //原数组的值作为新数组count的下标
            int index = array[i];//index为新数组count下标
            count[index-minVal]++; //计数
        }
        //此时说明计数数组中已经统计完每个数据出现的次数,后面只需遍历数组,将数据写出来即可,最后返回数组
        int indexArrray = 0; //定义一个新下标
        for (int i = 0; i < count.length; i++) {
            while (count[i] > 0) { //说明count[i]这里存放了数据出现的次数--》(count[i] 是数据i出现的次数
                array[indexArrray] = i+minVal; //一定要加minval,因为不一定就是i出现了count[i]
                count[i]--;//拷贝一次之后次数减少一个
                indexArrray++;//下标继续向后移动
            }
        }
    }

 11.topK问题

求解数组中前k个最小的元素--》大根堆完成

public class topK {
      public static int[] topK(int[] array,int k) {
//1.创建一个大小为k的大根堆
        PriorityQueue<Integer> maxHeap = new PriorityQueue<>(k, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2-o1;
            }
        });
//2.遍历数组中,前k个元素放到队列中
        for (int i = 0; i < array.length; i++) {
            if (maxHeap.size() < k) {
                maxHeap.offer(array[i]);//没超过k个元素,就继续往里面放元素
            }else {
//3.从第k+1个元素开始,每个元素与堆顶元素进行比较
                int top = maxHeap.peek(); //获取当前堆顶元素
                if (top > array[i]) { //如果当前元素<栈顶元素 ,
                    maxHeap.poll(); //弹出堆顶元素
                    maxHeap.offer(array[i]);  //存入堆顶元素
                }
            }
        }
        int[] tmp = new int[k];
        for (int i = 0; i < k; i++) {
            tmp[i] = maxHeap.poll();
        }
        return tmp;
    }

    public static void main(String[] args) {
        int[] array = {18,21,8,10,34,12};
        int[] tmp = topK(array,3);
        System.out.println(Arrays.toString(tmp));
    }
}



面试题1:查找和最小的 K 对数字

给定两个以 升序排列 的整数数组 nums1和nums2,以及一个整数 k
定义一对值 (u,v),其中第一个元素来自 nums1,第二个元素来自 nums2 。请找到  和最小的  k个数对 (u1,v1),  (u2,v2)  ...  (uk,vk) 。  list类型就可存放一对值

    public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) {
        PriorityQueue<List<Integer>> maxHeap = new PriorityQueue<>(k, new Comparator<List<Integer>>() {
            @Override
            public int compare(List<Integer> o1, List<Integer> o2) {
                return (o2.get(0)+o2.get(1))-(o1.get(0)+o1.get(1));
            }
        });
        for (int i = 0; i < Math.min(nums1.length,k); i++) {
            for (int j = 0; j < Math.min(nums2.length,k); j++) {
                if (maxHeap.size() < k) {
                    List<Integer> tmpList = new ArrayList<>();
                    tmpList.add(nums1[i]);
                    tmpList.add(nums2[j]);
                    maxHeap.offer(tmpList);
                }else {
                    int top = maxHeap.peek().get(0) + maxHeap.peek().get(1);
                    if (top > nums1[i]+nums2[j]) {
                        maxHeap.poll();
                        List<Integer> tmpList = new ArrayList<>();
                        tmpList.add(nums1[i]);
                        tmpList.add(nums2[j]);
                        maxHeap.offer(tmpList);
                    }
                }
            }
        }
        List<List<Integer>> ret = new ArrayList<>();
        for (int i = 0; i < k && !maxHeap.isEmpty();i++) {
            ret.add(maxHeap.poll());
        }
        return ret;
    }

11.测试数据运行时间


    //========================测试有序数据运行时间==================================================//
    public static void testTime1(int capacity) {
        int[] array = new int[capacity];
        for (int i = 0; i < array.length; i++) {
            array[i] = i;
        }
        long start = System.currentTimeMillis();
        insertSort(array);
        shellSort(array);
        selectSort(array);
        long end  =System.currentTimeMillis(); //时间单位毫秒
        System.out.println(end-start);
    }

    public static void main0(String[] args) {
        testTime1(10_0000);  //1745  说明了有序的时间更快

        testTime2(10_0000);  //5598
    }

    //========================测试无序数据运行时间==================================================//
    public static void testTime2(int capacity) {
        int[] array = new int[capacity];
        Random random = new Random();
        for (int i = 0; i < array.length; i++) {
            array[i] = random.nextInt(capacity);
        }
        long start = System.currentTimeMillis();
        insertSort(array);
        shellSort(array);
        selectSort(array);
        quickSort(array);
        long end  =System.currentTimeMillis(); //时间单位毫秒
        System.out.println(end-start);
    }



    public static void main1(String[] args) {
        int[] array = {12,5,18,10,4,2};
        int[] array1 = {12,99,18,11,4,2};
//        insertSort(array);
//        shellSort(array1);
//        selectSort(array1);
//        heapSort(array);
//        bubbleSorts(array1);
        quickSort(array);
        quickSort(array1);
        System.out.println(Arrays.toString(array));
        System.out.println(Arrays.toString(array1));
    }

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值