• Leetcode 1 最小的k个数


    题目要求:输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。

    此问题简单思路是排序, 我们分别利用直接插入排序,归并,快排, 堆排序来实现!

    直接插入排序, 时间复杂度O(n^2), 空间复杂度为O(1),  优化措施可以通过二分法来减少比较次数。

    **
         * 直接插入法 容易把条件tempt<arr[j]变为条件arr[i]<arr[j]
         **/
        public void directInsertOrderSort(int[] arr) {
            int tempt = 0, j = 0;
            for (int i = 1; i < arr.length; i++) {
                tempt = arr[i];
    // 可以优化利用二分法减少比较次数
    for (j = i - 1; j >= 0 && tempt < arr[j]; j--) { arr[j + 1] = arr[j]; } arr[j + 1] = tempt;
    } }

    二分查找优化, 虽然减少比较次数,在数据比较少的情况下时间复杂度还是很高。

            // 之前 0, i-1都是有序元素
                int low = 0, high = i - 1;
                while (low <= high) { // 二分查找优化
                    int mid = (low + high) / 2;
                    if (arr[mid] >= tempt) high = mid - 1;
                    else low = mid + 1;
                }
                for (j = i - 1; j >= high + 1; j++) {
                    arr[j + 1] = arr[j];
                }
                arr[high + 1] = tempt;

    快速排序------递归和非递归   平均时间复杂度O(nlogn), 如果数据基本有序,那么时间复杂度为O(n^2),空间复杂度最优是O(logn), 每次从中间分割. 最坏为O(n) 变成冒泡排序 

     /**
         * * 快速排序
         **/
        public void directQuickOrderSort(int[] arr, int low, int high) {
            /*if (low < high) {
                int mid = rQuickMindIndex(arr, low, high);
                directQuickOrderSort(arr, low, mid - 1);
                directQuickOrderSort(arr, mid + 1, high);
            }*/
            Stack<Integer> stack = new Stack<>();
            if (low < high) { // 非递归
                stack.push(high);
                stack.push(low);
                while (!stack.isEmpty()) {
    
                    low = stack.pop();
                    high = stack.pop();
                    int mid = rQuickMindIndex(arr, low, high);
                    if (mid - 1 > low) {
                        stack.push(mid - 1);
                        stack.push(low);
                    }
                    if (mid + 1 < high) {
                        stack.push(high);
                        stack.push(mid + 1);
                    }
                }
            }
        }
    
        public int rQuickMindIndex(int arr[], int low, int high) {
            int tempt = arr[low]; // 保存当前需要替换的值
            while (low < high) { //
                while (high > low && arr[high] >= tempt) high--;
                arr[low] = arr[high];
                while (low < high && arr[low] < tempt) low++;
                arr[high] = arr[low];
            }
    
            arr[low] = tempt;
            return low;
        }

    堆排序----> 此种方法是查找前k个数的最好方法, 空间复杂度为O(1), 首先维护一个k个元素的大顶堆,然后利用淘汰策略一个一个淘汰,组后输出这个堆。 

     /**
         * 堆排序  构建k个元素的大顶堆包括两步 堆调整,
         *
         */
        public void directHeapOrderSort(int[] arr, int k) {
            for (int i = k/ 2 - 1; i >= 0; i--) {
                // 调整数组中从i,.....len-1中数据使满足堆排序结构
                heapAdjust(arr, i, k);
            }
        }
    
        /**
         * 大顶堆的调整,
         * @param arr 数组
         * @param index 需要调整的元素索引位置
         * @param high 堆的元素个数
         */
        public void heapAdjust(int[] arr, int index, int high) {
            // 保存此位置上的数据信息
            int tempt = arr[index];
            for (int i = index * 2 + 1; i < high; i = i * 2 + 1) {
                if (i + 1 < high && arr[i + 1] > arr[i]) i++; //满足右边节点数据更小
                // 比较数据和index位置上数据的大小
                if (tempt < arr[i]) {
                    arr[index] = arr[i];
                    index = i;
                } else
                    break;
            }
            arr[index] = tempt;
        }

    归并排序  时间复杂度O(nlogn), 空间O(n), 需要一个辅助的拷贝数组空间。  

     public void directReclusiveOrderSort(int[] arr, int[] copy, int low, int high) {
    
            if (low >= high) return;
            int mid = (low + high) / 2;
            directReclusiveOrderSort(arr, copy, low, mid);
            directReclusiveOrderSort(arr, copy, mid + 1, high);
            directReclusiveAllToOneOrder(arr, copy, low, mid, high);
    
        }
    
        public void directReclusiveAllToOneOrder(int[] arr, int[] copy, int low, int mid, int high) {
    
            // 先每次新创建一个数组, 后期修改未全局创建一个数组
            //int[] copy=new int[1+high-low];
    
            int l1 = low, l2 = mid + 1, index = low;
    
            while (l1 <= mid && l2 <= high) {
                if (arr[l1] > arr[l2]) {
                    copy[index++] = arr[l2++];
                } else {
                    copy[index++] = arr[l1++];
                }
            }
    
            while (l1 <= mid) {
                copy[index++] = arr[l1++];
            }
            while (l2 <= high) {
                copy[index++] = arr[l2++];
            }
    
            for (int i = low; i <= high; i++) {
                arr[i] = copy[i];
            }
        }
  • 相关阅读:
    day49-线程-事件
    day48-线程-信号量
    180-spring框架开启事务的两种方式
    094-SSM框架和控制层,业务层、持久层是什么关系?
    179-当创建FileInputStream会发生什么呢?
    178-链接查询association
    177-properties文件的中文注释是会出现乱码的?
    176-@Mapper注解是什么?
    092-linux都是怎么安装文件的?
    178-什么是dns解析呢?
  • 原文地址:https://www.cnblogs.com/09120912zhang/p/12537083.html
Copyright © 2020-2023  润新知