5.第k大元素

描述

在数组中找到第k大的元素

注意事项

你可以交换数组中的元素的位置

样例

给出数组 [9,3,2,4,8],第三大的元素是 4
给出数组 [1,2,3,4,5],第一大的元素是 5,第二大的元素是 4,第三大的元素是 3,以此类推

挑战

要求时间复杂度为O(n),空间复杂度为O(1)

代码

class Solution {
    /*
     * @param k : description of k
     * @param nums : array of nums
     * @return: description of return
     */
    public int kthLargestElement(int k, int[] nums) {
        if (nums == null) {
            return -1;
        }
        
        return quickSelect(nums, 0, nums.length - 1, k);
    }
    
    private int quickSelect(int[] nums, int start, int end, int k) {
        int left = start;
        int right = end;
        // pivot必须是数值,不能是下标,因为快排不够稳定,同一下标对应的值在变化 
        int pivot = nums[start + (end - start) / 2];
        
        while (left <= right) {
            while (left <= right && nums[left] > pivot) {
                left++;
            }
            while (left <= right && nums[right] < pivot) {
                right--;
            }
            if (left <= right) {
                int temp = nums[left];
                nums[left] = nums[right];
                nums[right] = temp;
                left++;
                right--;
            }
        }
        
        // 递归时方法传递的形参要是变量,不能是具体值
        if (start + k - 1 <= right) {
            return quickSelect(nums, start, right, k);
        } else if (start + k - 1 >= left) {
           // start 只有第一轮从 0 开始,后续要减去 start
            return quickSelect(nums, left, end, k - (left - start));
        } else {
            return pivot;         // 也可以写成return nums[right + 1]
        }
    }
}

假设第 k 个数 key 的下标为i,如果 k < i,则第 K 大的数必然在快排左边的区域;如果 k = i,则 key 就是第 k 大的数;如果 k > i,则k必然在快排的右边的区域。
接下来递归即可得到第k大的数。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容