既然是要找到第K大的数,那么自然想到先排好序再输出。于是写了一个快速排序算法:
void mySort(vector<int>& vec, int left, int right) {
int i = left, j = right;
int mid = vec[(left + right) / 2];
while (i <= j) {
while (vec[i] < mid)
i++;
while (vec[j] > mid)
j--;
if (i <= j) {
int tmp = vec[i];
vec[i] = vec[j];
vec[j] = tmp;
i++;
j--;
}
}
if (left < j)
mySort(vec, left, j);
if (i < right)
mySort(vec, i, right);
}
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
int len = nums.size();
mySort(nums, 0, len - 1);
return nums[len - k];
}
};
虽然很快就AC了,但是毕竟在学分治算法,想尝试一下用分治怎么用。于是上网找了此题的分治做法,主要是通过pivot来重构数组,想法很妙:寻找第K大的数,即寻找降序数组中位于第K位置的值。要重构数组,先找一个数当成pivot,比它大的放在数组左边,比它小的放在数组右边,不断重复直到pivot位于数组的第K个位置。
void swap(vector<int>& vec, int i, int j) {
int tmp = vec[j];
vec[j] = vec[i];
vec[i] = tmp;
}
int partition(vector<int>& vec, int left, int right) {
int pivot = vec[left];
int i = left + 1, j = right;
while (i <= j) {
if (vec[i] < pivot && vec[j] > pivot) {
swap(vec, i, j);
i++;
j--;
}
if (vec[i] >= pivot)
i++;
if (vec[j] <= pivot)
j--;
}
swap(vec, left, j);
return j;
}
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
int len = nums.size();
int l = 0, r = len - 1;
while (1) {
int pos = partition(nums, l, r);
if (pos == k - 1)
return nums[pos];
else if (pos > k - 1)
r = pos - 1;
else if (pos < k - 1)
l = pos + 1;
}
}
};
其实用map来解这道题也是很方便的,算法思想有点类似桶排序,将数组元素当作键,元素出现的次数当作值,保存起来,最后输出第n-k+1小的数(即第k大的数):
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
map<int, int> m;
int len = nums.size();
for (int j = 0; j < len; j++) {
m[nums[j]]++;
}
map<int, int>::iterator it = m.begin();
k = len - k + 1;
while (k > (it->second)) {
k = k - (it->second);
it++;
}
return it->first;
}
};
除此之外,C++也有许多自带排序的数据结构,例如set、priority_queue,虽然对做算法题没有什么作用,但是可以作为一个实用的数据结构供我们今后使用。
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
multiset<int> q(nums.begin(), nums.end());
multiset<int>::iterator it;
int flag = 1;
int len = nums.size();
for (it = q.begin(); it != q.end(); it++, flag++) {
if (flag == len - k + 1)
break;
}
return *it;
}
};
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
priority_queue<int> q(nums.begin(), nums.end());
for (int i = 0; i < k - 1; ++i) {
q.pop();
}
return q.top();
}
};