1. 题目描述

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

示例 1:

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

示例 2:

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

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

2. 解题思路

最直接的思路就是对数组进行排序,然后直接返回排序后数组的倒数第k个元素。

除了使用sort()方法直接对数组进行排序之外,我们还可以使用快速排序对数组进行排序操作。正好也来复习一下快速排序算法。

我们知道数组从小到大排序之后,第K大元素就是索引为n-k的的值,那么n-k之前的值都比他小,n-k之后的值都比他大。我们可以把 n-k 看作 pivot ,之后用快速排序来解答。

3. 代码实现

  1. /**
  2. * @param {number[]} nums
  3. * @param {number} k
  4. * @return {number}
  5. */
  6. var findKthLargest = function(nums, k) {
  7. let res = nums.sort((a,b) => a-b)
  8. return res[res.length - k]
  9. };

快速排序:

  1. /**
  2. * @param {number[]} nums
  3. * @param {number} k
  4. * @return {number}
  5. */
  6. const findKthLargest = (nums, k) => {
  7. const n = nums.length;
  8. const quick = (l, r) => {
  9. if (l > r) return;
  10. let random = Math.floor(Math.random() * (r - l + 1)) + l; // 随机选取一个index
  11. swap(nums, random, r); // 将它和位置r的元素交换,让 nums[r] 作为 pivot 元素
  12. // 选定一个 pivot 元素,根据它进行分区。让左边的元素都比pivot小,右边的元素都比pivot大
  13. let pivotIndex = partition(nums, l, r);
  14. // 希望pivotIndex 正好是 n-k,如果小于他,则再其左边继续查找,如果大于他,就在其右边继续查找
  15. if (n - k < pivotIndex) {
  16. quick(l, pivotIndex - 1);
  17. } else {
  18. quick(pivotIndex + 1, r);
  19. }
  20. };
  21. quick(0, n - 1);
  22. return nums[n - k];
  23. };
  24. function partition(nums, left, right) {
  25. let pivot = nums[right];
  26. let pivotIndex = left;
  27. // 遍历数组,和pivot进行比较,如果比他小,就将他换到pivotIndex的位置
  28. for (let i = left; i < right; i++) {
  29. if (nums[i] < pivot) {
  30. swap(nums, i, pivotIndex);
  31. pivotIndex++;
  32. }
  33. }
  34. // 循环结束之后, pivotIndex左边都是比pivot小的数,让其与right交换,更新pivot元素
  35. swap(nums, right, pivotIndex);
  36. return pivotIndex;
  37. }
  38. // 交换函数
  39. function swap(nums, p, q) {
  40. const temp = nums[p];
  41. nums[p] = nums[q];
  42. nums[q] = temp;
  43. }

4. 提交结果

215. 数组中的第K个最大元素 - 图1
快速排序:
215. 数组中的第K个最大元素 - 图2