算法练习——前K小数

本文介绍了如何解决寻找数组中前K小的元素问题,无需排序。通过示例展示输入nums = {38, 61, 7, 87, 81, 18, 50, 55, 90, 26} 和 K = 7,输出结果为 {7, 18, 26, 38, 50, 55, 61}。文章提出两种方法,一种是直接排序,另一种利用分治思想,通过选定pivot并分组,递归找到前K小的元素。算法核心在于根据元素与pivot的关系划分数组并递归处理。" 111371950,10294852,STM32单片机配置上拉输入,"['嵌入式开发', 'STM32单片机', '电路设计', 'IIC通讯']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:给定一个数组,输出该数组前K小数(无需排序)

示例:

Input: nums = {38, 61, 7, 87, 81, 18, 50, 55, 90, 26} K = 7

Output: result = {7, 18, 26, 38, 50, 55, 61}


题解:

这道题目有两种解题方法,一是使用排序的算法让数组从小到大排好序,然后依次输出数组的前K个整数。

这样的做法对人而言虽然简单可操作性,但因为题目没有对数组排序的要求,使用排序算法无疑让计算机做了额外的工作。

另一种“偷懒”的做法是使用分治的思想,将原来的大数组不断地按照要求划分成更小的数组,最后得到一个长度为K的子数组,且该子数组内的所有元素的值都小于不在这个子数组内的元素的值。


算法的核心是,对于一个数组,选定数组第一个元素为pivot,然后遍历该数组,分别将值小于pivot、等于pivot、大于pivot的元素存放在数组l、m、r内,并计算三个数组的元素值分别为a、b、c

进行判断:

1.若K<=a,则前k小数全部落在数组l内,则继续对l进行递归调用,参数K不变

2.若K>a+b,则前k小数包括了数组l、m的全部元素,还有部分在r内,则对r进行递归调用,参数K变为K-a-b,然后将返回的数组与l、m合并

3.其他情况,说明第K小数恰好在m内,则将l、m合并


源代码:

vector<int> partition(vector<int> v, int k) {
	if (v.size() <= 1) return v;
	vector<int> l, m, r;
	int pivot = v[0];
	for (int i = 0; i < v.size(); i++) {
		if (v[i] < pivot) l.push_back(v[i]);
		if (v[i] == pivot) m.push_back(v[i]);
		if (v[i] > pivot) r.push_back(v[i]);
	}
	int a = l.size();
	int b = m.size();
	int c = r.size();
	if (k <= a) return partition(l, k);
	else if (k > a + b) {
		vector<int> rr = partition(r, k - a - b);
		l.insert(l.end(), m.begin(), m.end());
		l.insert(l.end(), rr.begin(), rr.end());
		return l;
	}
	else {
		l.insert(l.end(), m.begin(), m.end());
		return l;
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值