215. 数组中的第K个最大元素
个人思路
思路
通过对数组进行一些排序操作,使数组基本有序,进行求解
个人思路代码
mergeSort排序
class Solution {
public:
int maxn = 100005;
void merge(vector<int>& nums, int L1, int R1, int L2, int R2){
int i = L1, j = L2;
int temp[maxn], index = 0;
while(i <= R1 && j <= R2){
if(nums[i] >= nums[j]){
temp[index++] = nums[i++];
}
else{
temp[index++] = nums[j++];
}
}
while(i <= R1){
temp[index++] = nums[i++];
}
while(j <= R2){
temp[index++] = nums[j++];
}
for(int i = 0; i < index; ++i){
nums[L1 + i] = temp[i];
}
}
void mergeSort(vector<int>& nums, int left, int right){
if(left < right){
int mid = (left + right) / 2;
mergeSort(nums, left, mid);
mergeSort(nums, mid + 1, right);
merge(nums, left, mid, mid + 1, right);
}
}
int findKthLargest(vector<int>& nums, int k) {
int n = nums.size();
mergeSort(nums, 0, n - 1);
return nums[k - 1];
}
};
快排partition + 随机选取主元
- 通过快速排序随机划分主元,并完成一趟排序(降序),比主元小的元素在右边,比主元大的元素在左边
- judge的二分判断(与k-1进行比较),如果返回的主元位置恰好等于第k大的元素,返回元素值;若小于k-1,说明第k大元素在主元右侧,继续在右侧搜索;若大于k-1,说明第k大元素在主元左侧,继续在左侧搜索
速度有了明显的提升
class Solution {
public:
//基于快速排序的划分
int partition(vector<int>& nums, int left, int right){
srand((unsigned)time(NULL));
int p = round(1.0 * rand() / RAND_MAX * (right - left) + left);
swap(nums[p], nums[left]);
int temp = nums[left];
while(left < right){
while(left < right && nums[right] <= temp){
right--;
}
nums[left] = nums[right];
while(left < right && nums[left] > temp){
left++;
}
nums[right] = nums[left];
}
nums[left] = temp;
return left;
}
//对一趟快排后的序列进行判断
int judge(vector<int>& nums, int k){
int left = 0;
int right = nums.size() - 1;
while(left <= right){
int mid = partition(nums, left, right);
if(mid == k - 1){
return nums[mid];
}
else if(mid > k - 1){//主元位置大于k,说明第k个元素在左侧
right = mid - 1;
}
else{否则在右侧
left = mid + 1;
}
}
return -1;
}
int findKthLargest(vector<int>& nums, int k) {
return judge(nums, k);
}
};