215. Kth Largest Element in an Array
- Total Accepted: 116543
- Total Submissions: 305431
- Difficulty: Medium
- Contributors: Admin
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.
For example,
Given [3,2,1,5,6,4]
and k = 2, return 5.
解题过程:第二次遇到这个题了,上次是在学数据结构的时候,Ta留的作业中(有一些细微的差别,那道题是要输出前K大的数,不过思路都是一样的)。对于快速排序,总是感觉掌握的不牢,所以遇到可以用快排的题,还是要好好做一做。首先回忆快排的基本思路,每次找一个partition(这里默认partition就是数组首元素),然后从数组的开头和结尾分别扫描(first和last分别代表小于等于partition的第一个元素下标和最后一个元素下标),直到first=last,这时位于partition(也就是nums[first]=nums[last])之前的都比它小,位于它之后的都比它大。主要代码如下
while(first<last)
{
while(first<last&&nums[last]<=key) last--;
nums[first]=nums[last];
while(first<last&&nums[first]>=key) first++;
nums[last]=nums[first];
}
两个while循环代表两个扫描(这也是我认为的快排的代码核心)。然后就是处理本道题的思路,判断位于partition之前的元素是否大于K-1:1.若大于,则第K大的一定位于partition之前,此时对前部分元素继续用快排;2.若等于,则partition就是所求答案;3.若小于,则第K大的一定位于partition之后,对后部分元素用快排
这也就是divide and conquer思想
代码如下
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
return binary_search(nums, k,0,nums.size()-1);
}
private:
int binary_search(vector<int>& nums,int k,int low,int high)
{
int first=low,last=high;
int key=nums[first];
while(first<last)
{
while(first<last&&nums[last]<=key) last--;
nums[first]=nums[last];
while(first<last&&nums[first]>=key) first++;
nums[last]=nums[first];
}
nums[first]=key;
if((first-low)+1>k) return binary_search(nums,k,low,first-1);
else if((first-low)+1==k) return key;
else return binary_search(nums,k-((first-low)+1),first+1,high);
}
};
复杂度分析:
因为快排每次将数组划分为两组加一个枢纽元素,每一趟划分你只需要将k与枢纽元素的下标进行比较,如果比枢纽元素下标大就从右边的子数组中找,如果比枢纽元素下标小从左边的子数组中找,如果一样则就是枢纽元素,找到,如果需要从左边或者右边的子数组中再查找的话,只需要递归一边查找即可,无需像快排一样两边都需要递归,所以复杂度必然降低。
最差情况如下:假设快排每次都平均划分,但是都不在枢纽元素上找到第k大
第一趟快排没找到,时间复杂度为O(n),第二趟也没找到,时间复杂度为O(n/2),。。。。。,第k趟找到,时间复杂度为O(n/2k),所以总的时间复杂度为
O(n(1+1/2+....+1/2k))=O(n)