zoukankan      html  css  js  c++  java
  • LeetCode215. 数组中的第K个最大元素

    一、题目描述

    ☆☆二、解法

    方法1:基于快排的选择方法,即快排partition函数的应用。

    Note: 针对本题来说,快排的枢纽点要随机取,否则极端测试用例,会导致退化为O(n^2)

    方法2:基于堆排序的选择方法。

    解法1:

    class Solution {
        public int findKthLargest(int[] nums, int k) {
            int len = nums.length;
            int start = 0, end = len - 1;
            while (true){
                int pivotIndex = partition2(nums,start,end);
                if (pivotIndex == len - k) {
                    return nums[pivotIndex];
                }else if (pivotIndex < len - k) {
                    start = pivotIndex + 1;
                }else {
                    end = pivotIndex - 1;
                }
            }
        }
    
        /**
         *  快排partition函数:返回pivot的index,使得左边的值都比他小,右边的值都比它大
         */
        public int partition1(int[] nums, int start, int end) {
            int pivot = nums[start];
            while (start < end) {
                while (start < end && nums[end] >= pivot) {
                    end--;
                }
                swap(nums,start,end);
                while (start < end && nums[start] <= pivot) {
                    start++;
                }
                swap(nums,start,end);
            }
            return start; // 返回枢纽所在的位置
        }
    
        /**
         *  快排partition函数的优化版本
         *      优化思路:采用替换而不是交换的方式进行操作
         */
        public int partition2(int[] nums, int start, int end) {
            // 随机在arr[start...end]的范围中, 选择一个数值作为标定点pivot
            // Math.random()产生[0,1)的double型随机数,
            // 区间[a,b]的随机数 -> Math.random*(b-a+1)+a
    //        int pivot = nums[(int)Math.random()*(end-start+1) + start];
            int pivot = nums[start];
            while (start < end) {
                // 顺序很重要,要先从右往左找,如果右边的数比标准数大
                while (start < end && nums[end] >= pivot) {
                    end--;
                }
                // 使用右边的数字替换左边的数
                nums[start] = nums[end];
                while (start < end && nums[start] <= pivot) {
                    start++;
                }
                nums[end] = nums[start];
            }
            // 标准数归位
            nums[start] = pivot;
            return start;  // 返回枢纽所在的位置
        }
        public void swap(int[] nums, int a, int b) {
            int temp = nums[a];
            nums[a] = nums[b];
            nums[b] = temp;
        }
    }

    解法2:

    class Solution {
        public int findKthLargest(int[] nums, int k) {
            PriorityQueue<Integer> minHeap = new PriorityQueue<>();
            for (int num : nums) {
                minHeap.offer(num);
                if (minHeap.size() > k) {
                    minHeap.poll(); // 每次移除的就是堆中最小的值
                }
            }
            return minHeap.peek();
        }
    }

    参考:

    本题的多种解法见 通过 partition 减治 + 优先队列(Java、C++、Python)

     

  • 相关阅读:
    03-es6语法 Promise 和 es8语法 async await 的了解和基本使用
    02-遍历数组的方法
    01-操作数组的方法
    position 几个属性的作用
    javascript---split 和 join 的区别
    微信sdk (1)
    php获取post参数的几种方式
    linux循环递归设置权限
    php汉字截取
    php汉字生成首字母
  • 原文地址:https://www.cnblogs.com/HuangYJ/p/14092119.html
Copyright © 2011-2022 走看看