题目

Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.

Example 1:

  1. Input: [3,2,1,5,6,4] and k = 2
  2. Output: 5

Example 2:

  1. Input: [3,2,3,1,2,4,5,5,6] and k = 4
  2. Output: 4

Note:
You may assume k is always valid, 1 ≤ k ≤ array’s length.


题意

找到数组中第K大的数。

思路

最简单的方法是直接排序,再取第K大的数。

更高效的方法是分治法,利用快速排序的partition来选出第K大。


代码实现

Java

排序

  1. class Solution {
  2. public int findKthLargest(int[] nums, int k) {
  3. Arrays.sort(nums);
  4. return nums[nums.length - k];
  5. }
  6. }

分治法(二路快排)

  1. class Solution {
  2. public int findKthLargest(int[] nums, int k) {
  3. int left = 0, right = nums.length - 1;
  4. while (left < right) {
  5. int p = partition(nums, left, right);
  6. if (p < k - 1) {
  7. left = p + 1;
  8. } else if (p > k - 1) {
  9. right = p - 1;
  10. } else {
  11. return nums[p];
  12. }
  13. }
  14. return nums[k - 1];
  15. }
  16. private int partition(int[] nums, int left, int right) {
  17. int i = left, j = right + 1;
  18. // 随机选择一个元素当作参考标准(这一步很重要)
  19. int r = new Random().nextInt(right - left + 1) + left;
  20. swap(nums, left, r);
  21. int temp = nums[left];
  22. while (true) {
  23. while (nums[++i] > temp) {
  24. if (i == right) break;
  25. }
  26. while (nums[--j] < temp) {
  27. if (j == left) break;
  28. }
  29. if (i >= j) break;
  30. swap(nums, i, j);
  31. }
  32. swap(nums, left, j);
  33. return j;
  34. }
  35. private void swap(int[] nums, int i, int j) {
  36. int temp = nums[i];
  37. nums[i] = nums[j];
  38. nums[j] = temp;
  39. }
  40. }

分治法(三路快排)

  1. class Solution {
  2. public int findKthLargest(int[] nums, int k) {
  3. return partition(nums, 0, nums.length - 1, k);
  4. }
  5. private int partition(int[] nums, int left, int right, int k) {
  6. int i = left, p = left, q = right;
  7. int temp = nums[new Random().nextInt(right - left + 1) + left]; // 随机化很重要
  8. // 将指定范围数组分为三个区域
  9. while (i <= q) {
  10. if (nums[i] > temp) {
  11. swap(nums, i++, p++);
  12. } else if (nums[i] < temp) {
  13. swap(nums, i, q--);
  14. } else {
  15. i++;
  16. }
  17. }
  18. // 判断第K大在哪个区域,并对应处理
  19. if (k < p - left + 1) {
  20. return partition(nums, left, p - 1, k);
  21. } else if (k > q - left + 1) {
  22. return partition(nums, q + 1, right, k - q + left - 1);
  23. } else {
  24. return nums[p];
  25. }
  26. }
  27. private void swap(int[] nums, int i, int j) {
  28. int temp = nums[i];
  29. nums[i] = nums[j];
  30. nums[j] = temp;
  31. }
  32. }

JavaScript

  1. /**
  2. * @param {number[]} nums
  3. * @param {number} k
  4. * @return {number}
  5. */
  6. var findKthLargest = function (nums, k) {
  7. let left = 0, right = nums.length - 1
  8. while (left < right) {
  9. const p = partition(nums, left, right)
  10. if (p < k - 1) {
  11. left = p + 1
  12. } else if (p > k - 1) {
  13. right = p - 1
  14. } else {
  15. return nums[p]
  16. }
  17. }
  18. return nums[k - 1]
  19. }
  20. function partition(nums, left, right) {
  21. let tmp = nums[left]
  22. while (left < right) {
  23. while (left < right && nums[right] <= tmp) {
  24. right--
  25. }
  26. nums[left] = nums[right]
  27. while (left < right && nums[left] > tmp) {
  28. left++
  29. }
  30. nums[right] = nums[left]
  31. }
  32. nums[left] = tmp
  33. return left
  34. }