215-数组中的第K个最大元素

题目描述

在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

示例 1:

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

示例 2:

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

说明:

你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。


解题思路

使用快速排序的思想来解题

每次选择数组中最后一个元素作为目标值pivot,然后从头到尾扫描数组,使< pivot的元素在pivot左边,>= pivot的元素在pivot右边,再计算pivot在数组中的位置,(递归地)调整下一次quickSelect的范围。pivot偏大,下次就在左边找第k个;pivot偏小,下次就在右边找第k-m个。

Java 实现

public int findKthLargest (int[] nums, int k) {
    int n = nums.length;
    int p = quickSelect(nums, 0, n - 1, n - k + 1);
    return nums[p];
}

// 此处的 k 是按从小到大排的顺序
// return the index of the kth smallest number
private int quickSelect (int[] nums, int lo, int hi, int k) {
    int i = lo;
    int j = hi;
    int pivot = nums[hi];
    // < pivot 放左边
    // >= pivot 放右边
    while (i < j) {
        if (nums[i++] > pivot) swap(nums, --i, --j);
    }
    swap(nums, i, hi); // 将 pivot 放入正确位置

    // 计算 pivot 在数组中的位置
    int m = i - lo + 1;

    if (m == k) return i;
    else if (m > k) return quickSelect(nums, lo, i - 1, k);
    else return quickSelect(nums, i + 1, hi, k - m);
}

private void swap (int[] nums, int i, int j) {
    int temp = nums[i];
    nums[i] = nums[j];
    nums[j] = temp;
}

心得体会

快速排序的关键是正确地切分数组。


 上一篇
56-合并区间 56-合并区间
题目描述给出一个区间的集合,请合并所有重叠的区间。 示例 1: 输入: [[1,3],[2,6],[8,10],[15,18]] 输出: [[1,6],[8,10],[15,18]] 解释: 区间 [1,3] 和 [2,6] 重叠, 将它们
2019-03-15
下一篇 
34-在排序数组中查找元素的第一个和最后一个位置 34-在排序数组中查找元素的第一个和最后一个位置
题目描述给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。 你的算法时间复杂度必须是 O(log n) 级别。 如果数组中不存在目标值,返回 [-1, -1]。 示例 1: 输
2019-03-11
  目录