这是我参与8月更文挑战的第6天,活动详情查看:8月更文挑战
215. 数组中的第K个最大元素
给定整数数组 nums 和整数 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 个位置,这样平均时间复杂度是 O(nlogn),但其实我们可以做的更快。
我们先回顾一下快速排序
它的基本思想是:选择一个基准数,通过一趟排序将要排序的数据分割成独立的两部分;其中一部分的所有数据都比另外一部分的所有数据都要小。然后,再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
快速排序流程:
(1) 从数列中挑出一个基准值。
(2) 将所有比基准值小的摆放在基准前面,所有比基准值大的摆在基准的后面(相同的数可以到任一边);在这个分区退出之后,该基准就处于数列的中间位置。
(3) 递归地把"基准值前面的子数列"和"基准值后面的子数列"进行排序。
利用快速排序中的partition函数,我们可以找出一个中枢值,中枢值的左边元素均大于中枢值,中枢值的右边元素均小于中枢值,因此利用这个中枢值,我们可以每次都缩小区间,如果k是大于中枢值下标的说明我们只需要在中枢值的右边区间查找,否则就在左边区间查找
代码
class Solution {
public int findKthLargest(int[] nums, int k) {
int l=0,r=nums.length-1;
k=nums.length-k;
while (true)
{
int mid=partition(nums,l,r);
if (mid==k)
return nums[mid];
else if (mid<k)
l=mid+1;
else r=mid-1;
}
}
public int partition(int[] nums, int l,int r) {
int temp=nums[l];
while (l<r)
{
while (l<r&&nums[r]>=temp)
r--;
nums[l]=nums[r];
while (l<r&&nums[l]<=temp)
l++;
nums[r]=nums[l];
}
nums[l]=temp;
return l;
}
}