线性时间选择

原本想看看动态规划的,瞄到了一个线性时间选择的问题,之前看懂了又忘了,于是加深加深印象。

问题:

给定线性序集中n个元素和一个整数k,1<=k<=n,要求找出这n个元素中第k小的元素。

在这里插入图片描述
将元素每五个分为一组,分别找出中位数,再找到中位数的中位数。基于这个数进行快排。如此一来,每次都至少能分出1/4左右的元素,避免直接快排产生的最坏情况。 让人不禁感叹这就是大师的智慧。😲

代码:

#include<iostream>
#include<cstdio>
using namespace std;

void Swap(int &a, int &b)
{
	int temp;
	temp = a;
	a = b;
	b = temp;
}

void Quicksort(int nums[], int left, int right)//快排 
{
	if(left > right)return ;
	int low = left;
	int high = right;
	int key = nums[low];
	while (low < high)
	{
		while(low < high && nums[high] >= key) high--;
		nums[low] = nums[high];
		while(low < high && nums[low] < key) low++;
		nums[high] = nums[low];
	} 
	nums[low] = key;
	Quicksort(nums,left,low - 1);
	Quicksort(nums,low + 1,right);
}

int Partition(int nums[], int p, int r, int x)//数组从p到r,基于x快排 !一次 ! 
{
	if(r < p)return -1;
	int i; 
	for( i = p; i <= r; i++){
		if(nums[i] == x)break; //找到了x的i 
	}
	
	Swap(nums[i],nums[p]);
	
	int low = p;
	int high = r;
	int key = nums[low];
	while (low < high)
	{
		while(low < high && nums[high] >= key) high--;
		nums[low] = nums[high];
		while(low < high && nums[low] < key) low++;
		nums[high] = nums[low];
	} 
	
	nums[low] = key;  
	
	return low;
}



int Select(int nums[], int p, int r,int k)//数组从p到r,找到第k个 
{
	if(r - p < 75)
	{
		Quicksort(nums,p,r);
		return nums[p+k-1];
	} 
	
	for(int i = 0;i < (r-p-4)/5; i++)//分成5组 
	{
		Quicksort(nums,p+(i*5),p+(i*5)+4);//每组分别快排 
		Swap(nums[p+(i*5)+2],nums[p+i]);//集合各组的中位数 
	}
	  Quicksort(nums,p,p -1 + (r-p-4)/5);
	  int x = nums[p + (r-p-4)/10];
	  
	  int i = Partition(nums,p,r,x); //i是x的位置 ,x已被快排1次 
	  int j = i - p + 1;//j是x的排名 
	  
	  //如果k在x的右边 ,x前去掉 
	  if(k <= j) Select(nums,p,i,k);
	  else Select(nums,i+1,r,k-j);
				  

} 



int main()
{
	
	
	int x;
	//数组a存了0-79
	int a[80]= {3,1,7,6,5,9,8,2,0,4,13,11,17,16,15,19,18,12,10,14,23,21,27,26,25,29,28,22,20,24,33,31,37,36,35,39,38,32,30,34,43,41,47,46,45,49,48,42,40,44,53,51,57,56,55,59,58,52,50,54,63,61,67,66,65,69,68,62,60,64,73,71,77,76,75,79,78,72,70,74,
	           };
	cin>>x; 
	printf("第%d小的数是%d\n",x,Select(a,0,79,x));
	
	return 0;
}

看这俩哥的:
https://blog.csdn.net/vandance/article/details/82879085
https://blog.csdn.net/m0_37579232/article/details/80178000

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值