分治算法求N个数中第K小(大)的数

这个学期开算法课,跟着进度写写代码就好。这周讲分治,说到了求N个数中第K小(大)数的问题,写写看。

分治算法的复杂度是O(n),用到了快速排序的思路:先选取一个参考数进行一次快排,拿升序来说的话,快排之后左边所有数<参考数,右边所有数>参考数,然后根据左右部分各自包含元素的个数,计算要求的元素在哪个区间内(要求的元素或是左区间中的第k小数,或是右区间中第[k-j]小数,j为左区间的长度),然后递归求解。

本来pku 2104和pku 2761都是求第K小数的题,无奈用这个算法TLE,只能用后面的划分树或是其他复杂度更低的算法来做,以后再说吧。我这里只贴用这个算法做的,虽然交上去会TLE...

#include <iostream>
 
using namespace std;
 
int partition(int[], int, int);
int Select(int[], int, int, int); 
 
int main()
{
	int n, m;
	int l, r, k;
	int v[100002];
	int d[100002];
	cin >> n >> m;
	for (int i = 1; i <= n; i++) cin >> v[i];
	while (m--)
	{
		cin >> l >> r >> k;
		for (int j = l; j <= r; j++) d[j] = v[j];
		cout << Select(d, l, r, k) << endl;
	}
 	return 0;
}
 
//一次快速排序 
int partition(int s[], int l, int r)
{
	if (l < r)
	{
		int i = l;
		int j = r;
		int x = s[i];
		while (i < j)
		{
			while (i < j && s[j] >= x) j--;
			if (i < j) s[i++] = s[j];
			while (i < j && s[i] < x) i++;
			if (i < j) s[j--] = s[i];
		}
		s[i] = x;
		return i;
	}
	return -1;
}
 
//分治找K-th Number 
int Select(int s[], int l, int r, int k)
{
	if (l > r) return -1;
	if (l == r) return s[l];
	//得到中间数的下标 
	int i = partition(s, l, r);
	//j为左区间长度 
	int j = i - l + 1;
	//位置大就在左区间找,否则就在右区间找
	if (j == k) return s[i];
	else if (j > k) return Select(s, l, i, k);
	else return Select(s, i+1, r, k-j);
}

   
### 回答1: 分治算法可以用来解一个整的第k大元素。具体步骤如下: 1. 将组分成两个子组,左边的子组包含小于等于间值的元素,右边的子组包含大于间值的元素。 2. 如果左边的子组的长度大于等于k,则在左边的子继续查找第k大元素。 3. 如果左边的子组的长度小于k,则在右边的子查找第k - 左边子组长度 - 1大元素。 4. 重复以上步骤,直到找到第k大元素。 这个算法的时间复杂度为O(nlogn),其n为组的长度。 ### 回答2: 分治算法是一种经典的算法思想,通过将一个问题分解成若干个小问题,并分别解决,最后合并结果得到整个问题的解决方案。对于整的第k大元素的问题,我们可以运用分治算法进行解。 具体的方法如下: 1. 随机选择的一个数作为枢轴值(pivot),将小于枢轴值的放在它左边,大于它的放在它右边。 2. 计算出枢轴值在的位置 p (第 p 大元素)。 a. 如果 p == k,则找到了第 k 大元素,返回它的值。 b. 如果 p > k,则在枢轴值的左边继续查找第 k 大元素。 c. 如果 p < k,则在枢轴值的右边继续查找第 k-p 大元素。 3. 当在步骤2找到了第 k 大元素时,返回它的值。 4. 当在步骤2未能找到第 k 大元素时,重复执行步骤1-3。 由于每一次都将组分成了两个部分,所以每一次查找的时间复杂度为 O(n),因此总时间复杂度为 O(n log n)。 需要注意的是,为了防止出现最坏情况,需随机选择枢轴值,或者通过一定的方法选择每次划分的方向(例如:选择作为枢轴值),防止过多的元素分到一边,导致时间复杂度退化。 总之,利用分治算法解整第 k 大元素是一种高效的方法,其时间复杂度为 O(n log n),是解决这一问题的常用方法。 ### 回答3: 分治算法将问题分成小的子问题,然后将这些子问题的解合并成原问题的解。一个整的第k大元素就可以使用分治算法解。 首先选择一个pivot元素,将组分成两部分,一部分比pivot元素小,一部分比pivot元素大。如果这个pivot元素是第k大的元素,那么问题就得到了解决。 如果pivot元素不是第k大的元素,那么问题就被拆分成了两个子问题,分别对这两个子问题进行递归操作即可。只需要递归子可能存在第k大元素的那一部分。 快速选择算法采用的就是这种思路,可以快速地找到第k大元素。反复进行快速选择操作,直到找到第k大的元素为止。 快速选择算法的时间复杂度为O(n),其n为组的长度。由于每次操作只需要递归一个子问题,所以算法的空间复杂度为O(log n)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值