Kth Largest Element 解题报告

来源:互联网 发布:java对象锁和类锁 编辑:程序博客网 时间:2024/05/18 18:21

Kth Largest Element

Description

Find K-th largest element in an array.

Notice

You can swap elements in the array

Example

In array [9,3,2,4,8], the 3rd largest element is 4.

In array [1,2,3,4,5], the 1st largest element is 5, 2nd largest element is 4, 3rd largest element is 3 and etc.

Challenge

O(n) time, O(1) extra memory.

实现思路一:基于优先队列

我们可以先往数组中存k个数,然后遍历从k开始遍历数组元素,如果数组元素小于优先队列中最小的数,则踢出队列最小数,放入数组元素。
直到遍历完,我们就得到最大的k个数,然后取出这个k个数中最小的,就是我们要的第k个最大数。
算法实现如下:

import java.util.Map.Entry;class Solution {    /*     * @param k : description of k     * @param nums : array of nums     * @return: description of return     */    public int kthLargestElement(int k, int[] nums) {        // write your code here        PriorityQueue<Integer> queue = new PriorityQueue<>();        int length = nums.length;        for(int i = 0 ; i < k ; i ++){            queue.offer(nums[i]);        }        for(int i = k ; i < length; i++){            if(queue.peek() < nums[i]){                queue.poll();                queue.offer(nums[i]);            }        }        return queue.peek();    }};

实现思路二:基于剪枝快排

利用有限队列,我们的额外空间复杂度为o(k),时间复杂度为n*log(k)。
我们还有另一种实现方法,是基于快排,在每次选出基数并经过一次从大到小排序后,然后判断:
1. 如果基数就在第k-1位,则基数即为所求
2. 若在第k-1位后面,则取基数往后,继第k-1位
3. 若在第k-1位前面,则取基数往前,找第k-1位
经过1、2、3步不断迭代,最终必能找到最大的第k个数
具体实现代码如下所示:

class Solution {    /*     * @param k : description of k     * @param nums : array of nums     * @return: description of return     */    public int kthLargestElement(int k, int[] nums) {        return partition(nums,k-1,0,nums.length-1);    }    public int partition(int[] nums, int k, int left, int right){        if(left >= right){            return nums[left];        }        int begin = left, end = right;        int flag = nums[begin];        while(begin < end){            while(begin < end && nums[end] <= flag){                end--;            }            nums[begin] = nums[end];            while(begin < end && nums[begin] > flag){                begin++;            }            nums[end] = nums[begin];        }        nums[begin] = flag;        if(begin == k){            return nums[begin];        }else if(begin < k){//最大k数在右边            return partition(nums,k,begin+1,right);        }else{//在左边            return partition(nums,k,left,begin-1);        }    }}
1 0