• Leetcode NO.215 Kth Largest Element In An Array 数组中的第K个最大元素


    1.问题描述

    给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。

    请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

    2.测试用例

    示例 1
    输入: [3,2,1,5,6,4] 和 k = 2
    输出: 5
    
    示例 2
    输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
    输出: 4
    

    3.提示

    • 1 <= k <= nums.length <= 104
    • -104 <= nums[i] <= 104

    4.代码

    1.基于堆排序
    code
    /**
         * 基于堆排序
         *
         * @param nums nums
         * @param k    k
         * @return res
     */
    public int findKthLargestWithBigHeapSort(int[] nums, int k) {
        int n = nums.length;
        int heapSize = n;
        //构建大顶堆
        buildBigHeapify(nums, heapSize);
        //删除第 n - k个元素
        for (int i = n - 1; i > n - k; i--) {
            exchangeArrayEle(nums, 0, i);
            heapSize--;
            maxHeapfiy(nums, 0, heapSize);
        }
        //返回堆顶即可
        return nums[0];
    }
    
    
    /**
         * 构建大顶堆
         * @param nums 数组
         * @param heapSize 堆大小
    */
    private void buildBigHeapify(int[] nums, int heapSize) {
        for (int i = heapSize / 2 - 1; i >= 0; i--) {
            //递归构建
            maxHeapfiy(nums, i, heapSize);
        }
    }
    
    /**
         * 构建大顶堆
         * @param nums 数组
         * @param top 堆元素
         * @param heapSize 堆大小
    */
    private void maxHeapfiy(int[] nums, int top, int heapSize) {
        int left = top * 2 + 1;
        int right = top * 2 + 2;
        int largest = top;
    
        if (right < heapSize && nums[right] > nums[largest]) {
            largest = right;
        }
        if (left < heapSize && nums[left] > nums[largest]) {
            largest = left;
        }
        if (top != largest) {
            exchangeArrayEle(nums, top, largest);
            maxHeapfiy(nums, largest, heapSize);
        }
    }
    
    
    /**
         * 交换数组元素
         * 临时变量法
         *
         * @param nums 数组
         * @param i 待交换元素i
         * @param j 待交换元素j
     */
    public static void exchangeArrayEle(int[] nums, int i, int j) {
        Assert.assertNotNull(nums);
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }
    
    复杂度
    * 时间 O(nlogn)
    * 空间 O(logn)
    
    2.基于快速选择排序
    code
    /**
         * 基于快速选择排序
         * 时间 O(n) 证明过程可以参考《算法导论》9.2
         * 空间 O(nlongn)
         *
         * @param nums nums
         * @param k    k
         * @return res
     */
    public int findKthLargestWithQuickSelectSort(int[] nums, int k) {
        return quickSelect(nums, 0, nums.length - 1, nums.length - k);
    }
    
    /**
         * 快速选择(单路)排序
         * @param nums 数组
         * @param start 起始元素位置
         * @param end 结束元素位置
         * @param k 查找位置
         * @return
     */
    private int quickSelect(int[] nums, int start, int end, int k) {
        int partiton = randomPartiton(nums, start, end);
        if (partiton == k) {
            return nums[k];
        } else {
            return k < partiton ? quickSelect(nums, start, partiton - 1, k) : quickSelect(nums, partiton + 1, end, k);
        }
    }
    
    /**
         * 随机分区
         * @param nums 数组
         * @param start 起始元素位置
         * @param end 结束元素位置
         * @return
    */
    private int randomPartiton(int[] nums, int start, int end) {
        int random = start + new Random().nextInt(end - start + 1);
        SortUtils.exchangeArrayEle(nums, start, random);
        return partition(nums, start, end);
    }
    
    /**
         * 双指针快排
         * @param nums 数组
         * @param start 起始元素位置
         * @param end 结束元素位置
         * @return
     */
    private int partition(int[] nums, int start, int end) {
        int left = start, right = end;
        int povit = nums[start];
        while (left < right) {
            while (left < right && nums[right] >= povit) {
                right--;
            }
            while (left < right && nums[left] <= povit) {
                left++;
            }
            SortUtils.exchangeArrayEle(nums, left, right);
        }
        SortUtils.exchangeArrayEle(nums, left, start);
        return left;
    }
    
    复杂度
    * 时间 O(n) 
    * 空间 O(longn)
    
  • 相关阅读:
    BEGIN
    bdflush
    BASH BUILTIN COMMANDS 内建命令
    程序 算法与数据结构
    ThinkPHP 3.2.2 在 volist 多重循环嵌套中使用 if 判断标签
    Java实现 蓝桥杯 算法提高 矩形靶
    Java实现 蓝桥杯 算法提高 矩形靶
    Java实现 蓝桥杯 算法提高 矩形靶
    Java实现 蓝桥杯 算法提高 歌唱比赛
    Java实现 蓝桥杯 算法提高 歌唱比赛
  • 原文地址:https://www.cnblogs.com/worldline/p/15713540.html
Copyright © 2020-2023  润新知