思路参考:https://blog.csdn.net/love905661433/article/details/84930799
方法一:类似于冒泡法,取最后一个为基准,从前向后遍历,比基准数大就交换。
一次遍历完成之后,基准数位置减一,开始第二次比较。
重复k次,即可求得第k大元素。
方法二:参考自上述网址,采用三路快排。选取标定点,将数组分为比标定点大,和标定点相等,比标定点小三个部分。
定义两个指针sm,bi,和一个当前位置指针,则arr[0,sm]比标定点大,arr[sm+1,i-1]表示和标定点相等,arr[bi,n-1]表示比标定点小。判断排序后的标定点是否是第k大元素,如果不是,且比k大,则在比标定点大的范围内继续划分;比k小,在比标定点小的范围继续划分。
如果排成了从小打到的数组,则将k变为n-k+1代入即可。
时间复杂度:不太会计算,待求
swap(nums[lf], nums[mid]);这一步应该可以不要,不知道为何要加
#include<iostream>
#include<cassert>
#include<vector>
using namespace std;
class Solution1 {
public:
int findKthLargest(vector<int>& nums, int k) {
int left = 0;
int right = nums.size() - 1;
return partitionK(nums, left, right, nums.size() - k + 1);
}
int partitionK(vector<int>& nums, int lf, int rg, int targ) {
int i = lf;
int sm = lf - 1;
int bi = rg + 1;
int mid = lf + (rg - lf) / 2;
int im = nums[mid];
swap(nums[lf], nums[mid]);
while (i < bi) {
if (nums[i] < im) {
swap(nums[i], nums[sm + 1]);
sm++;
i++;
}
else if (nums[i] > im) {
swap(nums[i], nums[bi - 1]);
bi--;
}
else {
assert(nums[i] == im);
i++;
}
}
if (targ - 1 <= sm)
return partitionK(nums, lf, sm, targ);
else if (targ - 1 >= bi)
return partitionK(nums, bi, rg, targ);
else
return nums[targ - 1];
}
};
class Solution2 {
public:
int findKthLargest(vector<int>& nums, int k) {
int left = 0;
int right = nums.size() - 1;
return partitionK(nums, left, right, k);
}
int partitionK(vector<int>& nums, int lf, int rg, int targ) {
int i = lf;
int sm = lf - 1;
int bi = rg + 1;
int mid = lf + (rg - lf) / 2;
int im = nums[mid];
//swap(nums[lf], nums[mid]);
while (i < bi) {
if (nums[i] > im) {
swap(nums[i], nums[sm + 1]);
sm++;
i++;
}
else if (nums[i] < im) {
swap(nums[i], nums[bi - 1]);
bi--;
}
else {
assert(nums[i] == im);
i++;
}
}
if (targ - 1 <= sm)
return partitionK(nums, lf, sm, targ);
else if (targ - 1 >= bi)
return partitionK(nums, bi, rg, targ);
else
return nums[targ - 1];
}
};
int main(int argc, char** argv)
{
int A[] = {3,2,1,5,6,4};
vector<int> vec1(A, A+sizeof(A)/sizeof(int));
int result1;
result1 = Solution2().findKthLargest(vec1, 2);
cout << result1 << endl;
return 0;
}
方法三:使用堆, 维护一个元素个数为k的最大堆, 将所有数字放入到最大堆中, 全部放完之后, 最大堆中最小的那个元素就是第k个最大的元素。 这个方法以后再尝试。