leetcode215. 数组中的第K个最大元素(java)

265 篇文章 2 订阅
235 篇文章 0 订阅

leetcode215. 数组中的第K个最大元素

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/kth-largest-element-in-an-array

题目描述

给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。
请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。

示例 1:
输入: [3,2,1,5,6,4], k = 2
输出: 5

示例 2:
输入: [3,2,3,1,2,4,5,5,6], k = 4
输出: 4

提示:
1 <= k <= nums.length <= 100000
-10000 <= nums[i] <= 10000

分层减枝

题目明确要求时间复杂度是O(n)的复杂度,因此可以想到任何关于排好序在拿值的方法都是不符合要求的,因此排序算法,最好的时间复杂度也是N * log N ;是不符合要求的,即使语言本身实现的也不符合要求。

先演示一下暴力的解法 N * logN ,借助java 语言本身的排序算法。

	/**
	* 复杂度是N * log N
	*/
  public int findKthLargest(int[] nums, int k) {
        Arrays.sort(nums);
        return nums[nums.length - k];
    }

在解题前,先了解下快排算法:
快速排序(Quick Sort)是一种常用的排序算法,其基本思想是将一个数组按照某个关键字进行划分,将小于关键字的元素放在左侧,大于关键字的元素放在右侧,然后递归地对左右两个子数组进行排序,最终得到有序的数组。

怎么利用快排让复杂度降低为O(n)呢,看下上面快排的过程,选中一个数字后,
将小于关键字的元素放在左侧,大于关键字的元素放在右侧。这样数组大范围内上就是有序的,小范围内是无序的,根据大范围内有序,我们就可以淘汰掉一边,左边或者右边的数字,我们就可以淘汰掉,
这个里是找第K 大的元素,我们可以把过程改写下,让大于的放左边,小于的放右边,整体递减的顺序,这样方便查找。

代码演示

/**
     * 第K 大的元素。
     * @param nums
     * @param k
     * @return
     */
    public int findKthLargest(int[] nums, int k) {
       return numK(nums,0,nums.length - 1,k - 1);
    }

    /**
     * 快排分层
     * @param nums
     * @param L
     * @param R
     * @param k
     * @return
     */
    public int numK(int[]nums,int L,int R,int k){
        if (L == R){
            return nums[L];
        }
        //随机选中一个数字
        int pivot = nums[L + (int)(Math.random() * (R - L ))];
        //分层 大的在左边,小的在右边
        int[] partition = partition(nums, L, R, pivot);
        //在区间内,直接返回
        if (k >= partition[0] && k <= partition[1]){
            return nums[k];
        }else if (k > partition[1]){
            //下标大于右边界继续去右边选
            return numK(nums,partition[1] + 1,R,k );
        }else{
            //下标小于左边界继续去左边选
            return numK(nums,L,partition[0] - 1,k );
        }
    }

    /**
     * 分层 大的放左边,等于放中间,小于放右边。
     * @param arr
     * @param L
     * @param R
     * @param pivot
     * @return
     */
    public int[] partition(int[]arr,int L,int R,int pivot){
        int more = L - 1;
        int less = R + 1;
        int cur = L;
        while (cur < less){
            if (arr[cur] > pivot){
                swap(arr,++more,cur++);
            } else if (arr[cur] < pivot) {
                swap(arr,cur,--less);
            }else{
                cur++;
            }

        }
        return new int[]{more + 1, less - 1};
    }

    /**
     * 交换
     * @param nums
     * @param i
     * @param j
     */
    public void swap(int[]nums,int i,int j){
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }

KMP 算法

KMP–高效字符串匹配算法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值