第四章:分治 快排 题目:求前k大的数

题目:求前k大的数

给定一个数组包含n个元素,统计前m大的数并且把这m个数从大到小输
出。

输入:
第一行包含一个整数n,表示数组的大小。n < 100000。
第二行包含n个整数,表示数组的元素,整数之间以一个空格分开
。每个整数的绝对值不超过100000000。
第三行包含一个整数m。m < n。
输出:
从大到小输出前m大的数,每个数一行

思路:
最直接的利用c++自己的快排函数,但是这里介绍一下自己写的快排如何优化。
优化点:将前k的数都移到数组的右边,但不需要保证这些前k大的数之间是有序的。然后再对右边的k个数进行快排。

如何将前k大的都弄到最右边 :arrangeRight操作
1)设key=a[0], 将key挪到适当位置(利用快排的思想),使得比key小的元素都在
key左边,比key大的元素都在key右边(线性时间完成)
2) 选择数组的前部或后部再进行 arrangeRight操作-----降低了快排里面的两边都要进行

void arrangeRight(int a[], int s, int e, int k)
{
    if(s >= e)
        return;
    if(k == e-s+1)//判断区间是否为k,及时返回终止
        return;
    int i = s;
    int j = e;
    int key = a[s];//注意!!!!

    while(i != j)
    {
         while(i < j && a[j] >= key)
             --j;
         swapM(a[i],a[j]);
         while(i < j && a[i] <= key)
             ++i;
         swapM(a[i],a[j]);
    }//key值下标更换,但最后下标是i!!!!,可自己画图跟踪。
    //如果右边的数刚好为e-i+1为k个
    if(k == e - i + 1)
        return;
    //右边的数大于k个
    else if(k < e - i + 1)
    {
        arrangeRight(a,i+1,e,k);
    }
    //右边的数小于k个,需要左边取出k - (e-i+1)个
    else
    {
         arrangeRight(a,s,i-1,k-e+i-1);
    }
}

快排代码:

void quicksort(int a[],int l,int r)
{
	if(i==r)
		return ;
	int i=l,j=r,k=a[l];
	while(i != j){
		while(i<j&&a[i]<=k){
			i++;
		}
		swap(a[i],a[j]);
		while(j>i&&a[j]>=k){
			j--;
		}
		swap(a[i],a[j]);
	}
	//每次排序都保证了一个数的位置i,使左边的数都比这个数小,右边的都比这个数大 
	quicksor(a,l,i-1);
	quicksort(a,i+1,r);	
} 

**探讨:**快排和归并的区别
快排是从大到小(递归实现),归并是从小到大(递归实现),快排的定位,归并是捋顺

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值