选择问题(求N个数中第k个最大者)

方法1:

对这N个数进行排序,然后找出第k个最大者。

这是最容易想到的也是最容易写出来的方法,但这种方法效率很低,当N比较大的时候不适合用。

代码如下:

#include <iostream>
#include <vector>

using namespace std;

typedef vector<int> Vect;
typedef vector<int>::iterator Iter;

void sort(Vect &ivec);        //选择排序
int search(const Vect &ivec, int k); //查找第k大的元素

int main(void)
{
	int data[] = {4,6,3,7,2,8,1,9,0,5};
	Vect ivec(data, data + sizeof(data)/sizeof(int));
	
	sort(ivec);

	cout << search(ivec, 10) << endl;

	cin.get();
	return 0;
}


void sort(Vect &ivec)//选择排序
{
	Iter iter_i, iter_j;

	for(iter_i = ivec.begin(); iter_i != ivec.end()-1; ++iter_i)
	{
		Iter iter_k = iter_i;
		for(iter_j = iter_i+1; iter_j != ivec.end(); ++iter_j)
		{
			if(*iter_j > *iter_k)//升序排序
			{
				iter_k = iter_j;
			}
		}
		if(iter_i != iter_k)//移动元素
		{
			int temp = *iter_i;
			*iter_i = *iter_k;
			*iter_k = temp;
		}
	}
}

int search(const Vect &ivec, int k)//查找第k大的元素
{
	if(k > ivec.size())
	{
		cerr << "wrong" << endl;
	}
	else
	{
		return ivec.at(k-1);
	}
}


方法2:

对方法1进行修改,可以提高程序运行的效率。可以先读入k个元素并对其排序,接着将剩余的元素逐个读入。当读入一个新元素时,如果小于数组中的第k个元素,则忽略之,否则插入数组,将原来的第k个元素挤掉。

代码如下:

#include <iostream>
#include <vector>

using namespace std;

typedef vector<int> Vect;
typedef vector<int>::iterator Iter;

void sort(Vect &ivec, Vect::size_type k);  //对前k个元素进行选择排序
int search(Vect &ivec, Vect::size_type k); //查找第k大的元素

int main(void)
{
	int data[] = {4,6,3,7,2,8,1,9,0,5};
	Vect ivec(data, data + sizeof(data)/sizeof(int));

	cout << search(ivec, 5) << endl;

	cin.get();
	return 0;
}

void sort(Vect &ivec, Vect::size_type k)//对前k个元素进行选择排序
{
	Iter iter_i, iter_j;

	for(iter_i = ivec.begin(); iter_i != ivec.begin() + k -1; ++iter_i)
	{
		Iter iter_k = iter_i;
		for(iter_j = iter_i+1; iter_j != ivec.begin() + k; ++iter_j)
		{
			if(*iter_j > *iter_k)//升序排序
			{
				iter_k = iter_j;
			}
		}
		if(iter_i != iter_k)//移动元素
		{
			int temp = *iter_i;
			*iter_i = *iter_k;
			*iter_k = temp;
		}
	}
}

int search(Vect &ivec, Vect::size_type k)//查找第k大的元素
{
	if(k > ivec.size())
	{
		cerr << "wrong" << endl;
		return -1;   //标记错误信息,如果输入序列中有负数,则不能用-1,这里测试数据都是正数
	}
	
	sort(ivec, k);
	Vect::size_type flag = k;

	while(flag != ivec.size())
	{
		Iter iter = ivec.begin() + k-1;//标记第k个元素
		if(*iter < ivec.at(flag))      //如果后面的元素大于第k个元素,则按升序插入并挤掉第k个元素
		{
			while(iter != ivec.begin() && *(iter-1) < ivec.at(flag))//将所有比当前元素小的元素都后移一个位置
			{
				*iter = *(iter-1);
				--iter;
			}
			*iter = ivec.at(flag);//将当前元素插入
		}
		++flag;      //处理下一个元素
	}
	return ivec.at(k-1);
}

第三种方法:

如果元素个数是1000万呢,这样用以上两种方法都可以处理,但都需要很长的时间,这就需要改进算法了。先开辟一个很大的数组,其最大下标要大于输入元素中的最大元素,然后将输入的元素按下标存储,输入完以后遍历数组就可以得到第k大的元素了。

代码如下:

#include <iostream>
#include <vector>

using namespace std;

typedef vector<int> Vect;
typedef vector<int>::iterator Iter;

int main(void)
{
	Vect ivec(10000, 0);
	int n, k;

	cout << "请输入要输入元素的个数,以及要求第k大元素的k值:";
	cin >> n >> k;
	cout << "请输入元素:";

	for(int i=0; i<n; ++i)
	{
		int temp;
		cin >> temp;
		++ivec.at(temp);
	}

	for(Vect::size_type i = ivec.size()-1; i >= 0; --i)
	{
		if(k > 0 && ivec[i] != 0)
		{
			k -= ivec[i];
		}
		if(k <= 0)
		{
			cout << i << endl;
			break;
		}
	}

	cin.get();
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值