最小的K个数(快排思想) 2020-10-12

题目:

输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4。

思路:

sort排序后直接打印前 k 个数 , 时间复杂度为 nlogn 。
创建一个容量为k的大根堆的优先队列 ,遍历数组, 同时维护这个大根堆 。时间复杂度为O(nlogK);

进阶:

要求不能用全局排序 , 要求时间复杂度达到最低 , 要求不能用辅助空间。

思路:

快排思想:
对于快排 , 我们知道每一趟快排都可以确定一个元素在排序后的正确位置 , 设这个被确定的元素为 p ,但 p + 1 == k 时说明下标为p的元素已经排序好位置是数组的第K小 , 根据快排确定后 , p 的左边所有元素都会小于 p , 所有原数组从 0 到 p 的所有元素 就是要输出的正确答案。如果 p + 1 大于k 或者小小于 k 可以用二分来确定下一次我们要定位的元素小标 , 直到 p + 1 == k 。
空间复杂度: 原地修改数组的元素 , 所有O(0);
时间复杂度 : 每一次定位p 的 数据大小为 n + n/2 + n/4 + … = 2n 每次都舍弃上次数据的二分之一 , 最快一次就能定位出来 O(n) 最坏为O(n*n) 平均复杂度为O(n);

代码:

#include<bits/stdc++.h>
using namespace std;

int quickSort(vector<int>& arr , int l , int r){
	int base = arr[r];
	int i = l;
	for(int j = l ; j < r ; ++j){
		if(arr[j] < base){
			swap(arr[i++] , arr[j]);
		}
	}
	swap(arr[i] , arr[r]);
	return i;
}
vector<int> solution(vector<int>& arr , int k ){
	if(k == 0 || k > arr.size())return {};
	int l = 0 , r = arr.size() - 1;
	while(l <= r){
		int p = quickSort(arr , l , r);
		if(p + 1 == k)return {arr.begin() , arr.begin() + k};
		if(p + 1 > k)r = p - 1;
		else l = p + 1; 
	}
	return {};
}
/*int solution2(vector<int>& arr , int k ){
	if(k == 0 || k > arr.size())return -1;
	int l = 0 , r = arr.size() - 1;
	while(l <= r){
		int p = quickSort(arr , l , r);
		if(p + 1 == k)return arr[p];
		if(p + 1 > k)r = p - 1;
		else l = p + 1; 
	}
	return -1;
}*/
int main()
{
	vector<int>arr{5,1,6,3,7,2,8 ,3, 4}; 
	int k = 1;
	vector<int>ans = solution(arr , k);
	for(int v : ans){
		cout << v << " ";
	}
	cout << endl;
	cout << "-------------------"<<endl;
	cout << solution2(arr , 4);
	return	 0;
 }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值