Kth Largest Element 解题报告

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值