215. Kth Largest Element in an Array (Medium)
这道题很简单,给出最大的第K个数,从大到小排序之后return nums[k-1]就可以
,我这里用的冒泡排序,效率很低。
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
for(int i=0;i<nums.size()-1;i++)
{
for(int j=0;j<nums.size()-i-1;j++)
{
if(nums[j]<nums[j+1])
{
int temp=nums[j];
nums[j]=nums[j+1];
nums[j+1]=temp;
}
}
}
return nums[k-1];
}
};
尝试加了个flag标志后仍然效率提高不了啥。
或者直接用sort()
#include <stdio.h>
#include <vector>
#include <algorithm>
using namespace std;
class Solution
{
public:
int findKthLargest(vector<int> &nums, int k)
{
int result = 0;
int numsSize = int(nums.size());
if (numsSize == 0 || k > numsSize)
{
return 0;
}
sort(nums.begin(), nums.end());
result = nums[numsSize - k];
return result;
}
};
这道题目虽然简单但是常考优化:
所以这里写上两种要记住的方式:
1.堆
先介绍下优先队列
//升序队列
priority_queue <int,vector,greater > q;
就是说q这个队列里面的元素都是按升序排列好的(队头是最小的)
那么我们只需要不停的把元素放入优先队列
它会自动排序
然后稳定好队列的长度为k即可
如果长度超过k了,那就出队队头,即队列中最小的元素
最后返回队列的队头,即为第k大的元素
//代码3:优先队列/小顶堆
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
//升序的优先队列
priority_queue <int,vector<int>,greater<int> > ascending;
for (int &i:nums)
{
ascending.push(i);
if (ascending.size()>k)
ascending.pop();
}
return ascending.top();
}
};
2.快速选择
快排的思想是:找准一个基准,把小于基准的全部丢基准左边,把大于基准的全部丢在基准的右边
完成一个基准的位置后,基准这个地方的值是不会改变的
按照快排,应该是对基准的左边和右边进行递归,实现快排
这里就可以借助快排的思想,
既然完成一次基准的排序后,基准这个地方的值是确定的
即nums[基准值的位置]一定是第(基准的位置)小的元素(是按升序排列,最左边最小)
所以我们就判断这个最后(基准值的位置)是不是(nums.size()-k)即可
如果不是,我们只需对基准的左半部分或右半部分进行递归
直到找到(基准值的位置)是(nums.size()-k)即可
//代码2:快排
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
int index=nums.size()-k;//倒数第K个,这里是从小到大排序
return quick_sort(nums,0,nums.size()-1,index);
}
int quick_sort(vector<int>& nums,int low,int high,int& index)
{
int povitkey=nums.at(low),left=low,right=high;
while (left<right)
{
while (left<right)
if (nums.at(right)<povitkey)
{
nums.at(left)=nums.at(right);
++left;
break;
}
else
--right;
while (left<right)
if (nums.at(left)>povitkey)
{
nums.at(right)=nums.at(left);
--right;
break;
}
else
++left;
}
nums.at(left)=povitkey;
if (left==index)
return povitkey;
else if (left>index)
return quick_sort(nums,low,left-1,index);
else
return quick_sort(nums,left+1,high,index);
}
};
补充一个效率很高的做法:
int findKthLargest(vector<int>& nums, int k) {
int size = nums.size();
for (int i = 0; i < size; i ++) {
siftup(nums,i); // 把原来nums变成大顶堆
}
while(--k) {
remove(nums); // 依k-1次删顶
}
return nums[0];
}
void remove(vector<int>& nums) {
int size = nums.size();
// 最后一个元素覆盖顶元素,并删除最后一个元素
nums[0] = nums[size-1];
nums.erase(nums.begin() + size-1);
siftDown(nums,0);
}
void siftDown(vector<int>& nums, int index) {
int element = nums[index];
int size = nums.size();
int half = size >> 1;
while (index < half) { // index 必须是非叶子
int leftChildIndex = (index<<1)+1;
int rightChildIndex = leftChildIndex +1;
// 左子节点 < 右子节点 (这里要拿到最大子节点交换)
if (rightChildIndex < size && nums[leftChildIndex] < nums[rightChildIndex]) {
leftChildIndex = rightChildIndex;
}
// 如果左右子节点不大于它就停
if (element >= nums[leftChildIndex]) break;
// 交换子父节点
nums[index] = nums[leftChildIndex];
nums[leftChildIndex] = element;
index = leftChildIndex;
}
nums[index] = element;
}
void siftup(vector<int>& nums, int index) {
int element = nums[index];
while(index > 0) {
int parentIndex = (index-1) >> 1;
int parentElement = nums[parentIndex];
if(element <= parentElement) break;
nums[index] = parentElement;
nums[parentIndex] = element;
index = parentIndex;
}
nums[index] = element;
}
347. Top K Frequent Elements (Medium)
451. Sort Characters By Frequency (Medium)
75. Sort Colors (Medium)