算法之查找第k小的数和查找最小的k个元素

 

         利用快速排序的思想查找第k小的数,主要的核心思想还是快速排序的分治算法,具体的思路是这样的:

1 利用快排的partion函数将数组分成左右两个部分,

2  如果p刚好等于k,则说明p位置的数,就是我们要找的数,如果分出来的边界位置p小于给定的数k,我们知道最小的第k个数,肯定在p的右边,如果p大于给定的k则在p边界的左边

3 递归在p的左边或者右边查找

注:p为数组下标需要加1,一般会使用随机数,即在数组中随机选取一个数作为每次分边界的值。

具体的细节可以查看《算法导论》第九章,下面是简单的实现代码,没有完全验证过;

/*
查找第k小的数
*/
#include <iostream>

using namespace std;

int partion(int array[],int s,int e)
{
    int temp = array[s];
    while(s < e)
    {
        while(array[e] >= temp&& s<e )
            e--;
        if(s < e)
            array[s] = array[e];
        while(array[s] < temp && s<e)
            s++;
        if(s < e)
            array[e] = array[s];
    }
    array[s] = temp;
    return s;
}

int search_k(int array[],int s,int e,int k)
{
    int p = partion(array,s,e);
    int q = p+1;
    if( q == k )
        return array[p];
    if( q < k)
        return search_k(array,p+1,e,k);
    if( q > k)
        return search_k(array,s,p-1,k);
}


int main()
{
    int array[1000];
    int n;
    int k;
    while( cin >> n >> k && n!=0)
    {
        for(int i=0;i<n;i++)
            cin >> array[i];

        cout << search_k(array,0,n-1,k) << endl;
    }
}

        查找最小的k个数,我用上面的方法肯定也是可以的,只需要将分界的p返回,p左边的数(包括p位置本身),就是我们需要的所有的最小的k个数,简单验证过,还可以维护一个集合数据的个数为k,每次从数组中取出一个数,如果集合中的数字的个数小于k,则认为集合中的所有数都是最小的k个数,如果集合中的的数据的个数大于k了,则每次将最大的数置换出来,遍历完数组之后,集合中的k个数就是最小的k个数的集合,用c++ 中的STL可以简单实现下面的代码:

#include <iostream>
#include <set>
#include <vector>

using namespace std;

typedef multiset<int,greater<int> > IntHeap;

void FindLeastKNum(vector<int> &ivec,
					int k,
					IntHeap &leastNum)
{
	for(vector<int>::iterator iter= ivec.begin();
			iter != ivec.end(); iter++)
	{
				//	cout << *iter  << " ";
		if(leastNum.size() < k)
			leastNum.insert(*iter);
		else
		{
			IntHeap::iterator Tmpiter = leastNum.begin();	//
					//		cout <<"the  biggest"<< *Tmpiter <<endl;
			if(*iter < *Tmpiter)
			{
					leastNum.erase(Tmpiter);
					leastNum.insert( *iter );
			}
			
		}
	}
}

int main()
{
	int n;
	cin>> n ;
	vector<int> ivec;
	while(n--)
	{	
		int num =0;
		cin >> num;
		ivec.insert(ivec.begin(),num);	
	}
	int k;
	cin >> k;
	IntHeap leastNum;
	FindLeastKNum(ivec,k,leastNum);

	cout << "the  least k nums are: " <<endl;
	for(IntHeap::iterator iter=leastNum.begin();
		iter != leastNum.end(); iter++)
		cout << *iter << " ";
	cout <<endl;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值