输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4。
解题思路
- 排序后遍历(相当于简化后的暴力)O(logn)
- 借助快排的Partition思想O(n)
上代码(C++香)
法一:排序后遍历(相当于简化后的暴力)
class Solution {
public:
void mySwap(vector<int> &num, int i, int j){
int temp = num[j];
num[j] = num[i];
num[i] = temp;
}
int myPartition(vector<int> &num, int low, int high){
int pivot = num[low];
while(low < high){
// 将右边比pivot小的放到左边
while(low < high && num[high] >= pivot)
high--;
mySwap(num, low, high);
while(low < high && num[low] <= pivot)
low++;
mySwap(num, low, high);
}
return low;
}
// 快排
void QSort(vector<int> &num, int low, int high){
if(low >= high)
return ;
int pivot = myPartition(num, low, high);
QSort(num, low, pivot - 1);
QSort(num, pivot + 1, high);
}
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
vector<int> ans;
if(k > input.size())
return ans;
QSort(input, 0, input.size() - 1);
for(int i = 0; i < k; i++)
ans.push_back(input[i]);
return ans;
}
};
法二:借助快排的Partition思想
得到pivot如果与k-1相等,那么数组左边的数已经就比num[k-1]小了,所以找到这个pivot就行。
void mySwap(vector<int> &num, int i, int j){
int temp = num[j];
num[j] = num[i];
num[i] = temp;
}
int myPartition(vector<int> &num, int low, int high){
int pivot = num[low];
while(low < high){
// 将右边比pivot小的放到左边
while(low < high && num[high] >= pivot)
high--;
mySwap(num, low, high);
while(low < high && num[low] <= pivot)
low++;
mySwap(num, low, high);
}
return low;
}
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
vector<int> ans;
int length = input.size();
if(k > length)
return ans;
int low = 0;
int high = length - 1;
int pivot = myPartition(input, low, high);
while(pivot != k - 1){
// k-1在左边继续找
if(pivot > k - 1){
high = pivot - 1;
pivot = myPartition(input, low, high);
}
else{
low = pivot + 1;
pivot = myPartition(input, low, high);
}
}
for(int i = 0; i < k; i++)
ans.push_back(input[i]);
return ans;
}