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)

     

  • 相关阅读:
    September 17th 2016 Week 38th Saturday
    【2016-09-16】UbuntuServer14.04或更高版本安装问题记录
    September 16th 2016 Week 38th Friday
    September 11th 2016 Week 38th Sunday
    September 12th 2016 Week 38th Monday
    September 10th 2016 Week 37th Saturday
    September 9th 2016 Week 37th Friday
    c++暂停
    八皇后问题
    ( 转转)Android初级开发第九讲--Intent最全用法(打开文件跳转页面等)
  • 原文地址:https://www.cnblogs.com/HuangYJ/p/14092119.html
Copyright © 2011-2022 走看看