求最小的K个数 ,第K大的数
题目描述
思路1 使用长度为K的最大堆
举例说明
- [4 5 1 6_max]
- push(2) [2,4, 5 1 6_max] pop(6_max)
- get [2,1,4,5]
C++ 代码
- 也可以使用make_heap 算法
class Solution {
public:
vector<int> getLeastNumbers(vector<int>& arr, int k) {
// 如果用最大堆 [4 5 1 6_max]
// push(2) 【2,4, 5 1 6_max】 pop(6_max)
// [2,1,4,5]
std::priority_queue<int > priorityA;
for(int i=0;i<k;i++)
{
priorityA.push(arr[i]);
}
for(int i=k;i<arr.size();i++)
{
priorityA.push(arr[i]);
priorityA.pop();
}
std::vector<int> res;
while(!priorityA.empty())
{
res.push_back(priorityA.top());
priorityA.pop();
}
return res;
}
};
思路2 使用快排中的portion 即分治
- 给定pivot 确保左小右大
- 返回给定pivot在新序列中的位置 ( retIdx)
- when retIdx < k 说明[...retIdx,retIdx+1,...k ,k+1...]
portion(pivot= arr[retIdx+1],left=retIdx+1,right= arr.size()-1)
when retIdx> k 说明[...,k-1,k,...retIdx-1,retIdx,...arr.size]
portion(pivot= arr[retIdx-1],left=0,right=retIdx-1)
when retIdx=k ,return arr[0,retIdx]
调试用的代码
class Solution {
public:
int myPortion(vector<int>& arr, int left,int right)
{
int pivot= arr[left];
int aI=left,bI=right;
// [3,5,4,1,9]
// [3,1,4,5,9]
while(aI<=bI)
{
//左边 找到第一个大于pivot的
while(aI<=bI && arr[aI] <= pivot )
{
aI ++;
}
//右边 逆向寻找 找到一个小于pivot
while(aI<=bI && arr[bI] >= pivot)
{
bI--;
}
std::swap(arr[aI], arr[bI]);
}
std::swap(arr[aI], arr[left]);
for(auto x: arr) std::cout << x << " ";
std::cout << std::endl;
return aI;
}
vector<int> getLeastNumbers(vector<int>& arr, int k) {
// 利用qsort portion
// 给定axis 确保左小右大
// 返回axis在新序列中的位置 is retIdx
// when retIdx < k 说明[...retIdx,retIdx+1,...k ,k+1...]
// portion(arr[retIdx+1],left=retIdx+1,right= arr.size()-1)
// when retIdx> k 说明[...,k-1,k,...retIdx-1,retIdx,...arr.size]
// portion(arr[retIdx-1],left=0,right=retIdx-1)
// when retIdx=k ,return arr[0,retIdx]
int retIdx = myPortion(arr,0, arr.size()-1);
while( retIdx!=k )
{
if(retIdx<k ) retIdx= myPortion(arr,retIdx+1,arr.size()-1);
else retIdx = myPortion(arr,0, retIdx-1);
}
std::vector<int> res(arr.begin() ,arr.begin()+k);
return res;
}
};
采用递归优化后的代码
class Solution {
public:
int portion(std::vector<int>& arr,int left,int right)
{
int pivotnum = arr[left];
int i = left, j = right;
while (i<j)
{
//j= less pivotnum ,from right
while ( i<j && arr[j] >= pivotnum )
{
j--;
}
//这里pivot = arr[i] , 因有备份,可在这里赋值
arr[i] = arr[j];
//i= greater than pivotnum ,from left
while (i<j && arr[i] <= pivotnum)
{
i++;
}
arr[j] = arr[i];
}
arr[i] = pivotnum;
// for(auto x: arr) std::cout << x << " ";
// std::cout << std::endl;
return i;
}
int FindKth(std::vector<int>& arr,int left,int right,int k)
{
int idx=portion(arr,left,right);
if(idx>k)
{
return FindKth(arr,left,idx-1,k);
}else if(idx< k)
{
return FindKth(arr,idx+1,right,k);
}
return arr[idx];
}
vector<int> getLeastNumbers(vector<int>& arr, int k)
{ if(k==0) return {};
if(k==arr.size() ) return arr;
vector<int>res;
FindKth(arr,0,arr.size()-1,k);
for(int i=0;i<k;i++)
{
auto x=arr[i];
// auto x=FindKth(arr,0,arr.size()-1,i);
res.push_back(x);
}
return res;
}
};