215. 数组中的第K个最大元素(Java) Leecode

在这里插入图片描述
解题思路:

可以直接用二叉堆过滤数组。

public int findKthLargest(int[] nums, int k) {
		//最小二叉堆,最小元素再上面
        PriorityQueue<Integer> pq = new PriorityQueue<>();
		
        for(int i : nums){
            //过滤每个元素
            pq.offer(i);
            //只要堆大于k,就弹出元素,最后过滤完剩下的顶部元素就是第K大的元素。
            if(pq.size() > k){

                pq.poll();

            }
        }

        return pq.peek();
    }

时间复杂度:O(NlogK)

下面是一种优化方法,利用随机选择排序方法,时间复杂度为O(n)

    public int findKthLargest(int[] nums, int k) {
        int low = 0, high = nums.length - 1;
        int target = nums.length - k; //改变索引

        while(true){
            int i = partition(nums, low, high);
            if(target == i){
                return nums[target];
            }else if(i < target){
                low = i + 1;
            }else{
                high = i - 1;
            }
        }
    }


    private int partition(int[] arr, int low, int high) {
    //保持序列随机性,避免时间复杂度最坏情况n^2
    if(high > low){
        int random = low + new Random().nextInt(high - low);
        swap(arr, high, random);
    }
/**
     * 分区函数,将 arr[high] 作为 pivot 分区点
     * i、j 两个指针,i 作为标记“已处理区间”和“未处理区间”的分界点,也即 i 左边的(low~i-1)都是“已处理区”。
     * j 指针遍历数组,当 arr[j] 小于 pivot 时,就把 arr[j] 放到“已处理区间”的尾部,也即是 arr[i] 所在位置
     * 因此 swap(arr, i, j) 然后 i 指针后移,i++
     * 直到 j 遍历到数组末尾 arr[high],将 arr[i] 和 arr[high](pivot点) 进行交换,返回下标 i,就是分区点的下标。
     */
    int i = low;
    int pivot = arr[high]; //arr[high]处在随机位置
    for (int j= low; j < high; j++){
        if(arr[j] < pivot){
            swap(arr,i, j);
            i++;
        }
    }
    
    swap(arr, i, high);
    return i;
    }
	
    void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Not_Today.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值