剑指offer:面试题30,求最小的K个数

方法一:快速排序法

见剑指offer——面试题30

#include<iostream>
using namespace std;
int partition(int *input,int n,int s,int t)
{
	if(input==NULL||n<=0||s<0||t>n-1)
		return 0;
	int tmp;
	if(s<t)
	{
		tmp=input[s];
		while(s<t)
		{
			while(s<t&&input[t]>=tmp)
				t--;
			input[s]=input[t];
			while(s<t&&input[s]<=tmp)
				s++;
			input[t]=input[s];
		}
		input[s]=tmp;
	}
	return s;
}


void getleastnumbers(int *input,int n,int *output,int k)
{
	if(input==NULL||output==NULL||k>n||n<=0||k<=0)
		return;
	int start=0;
	int end=n-1;
	int index;
	index=partition(input,n,start,end);
	while(index!=k-1)
	{
		if(index>k-1)
		{
			end=index-1;
			index=partition(input,n,start,end);
		}
		else
		{
			start=index+1;
			index=partition(input,n,start,end);
		}
	}
	for(int i=0;i<k;i++)
		output[i]=input[i];
 }
int main()
{
	int input[]={4,5,1,6,2,7,3,8,3};
	int output[9];
	int k;
	cin>>k;
	getleastnumbers(input,9,output,k);
	for(int i=0;i<k;i++)
		cout<<output[i]<<" ";
	cout<<endl;
	return 1;
}
当数组中有重复数字也可以进行处理,如运行结果:


方法二:用set或multiset法

set/multiset相关知识

set是STL中一种标准关联容器(vector,list,string,deque都是序列容器,而set,multiset,map,multimap是标准关联容器),它底层使用平衡的搜索树——红黑树实现,插入删除操作时仅仅需要指针操作节点即可完成,不涉及到内存移动和拷贝,所以效率比较高。set,顾名思义是“集合”的意思,在set中元素都是唯一的,而且默认情况下会对元素自动进行升序排列,支持集合的交(set_intersection),差(set_difference) 并(set_union),对称差(set_symmetric_difference) 等一些集合上的操作,如果需要集合中的元素允许重复那么可以使用multiset.

重要知识点

1)multiset默认是按递增顺序排列的,要按递减顺序排可以这样

multiset<int,greater<int> > intset;

2)multiset的迭代器

typedef multiset<int,greater<int> >::iterator setIterator;

遍历元素的过程是:

for(setIterator it=myset.begin();it!=myset.end();++it)
		cout<<*it<<" ";

3)访问操作

第一个元素:setIterator first=leastnumbers.begin();

插入元素:intset.insert(var);

删除元素:inset.erase(first);


实现源码:


#include<iostream>
#include<set>
using namespace std;
typedef multiset<int,greater<int> > intset;
typedef multiset<int,greater<int> >::iterator setIterator;

void getleastnumbers(int *input,int n,intset &leastnumbers,int k)
{
	leastnumbers.clear();
	if(k<1||n<k)
		return;
	for(int i=0;i<n;i++)
	{
		if(leastnumbers.size()<k)
			leastnumbers.insert(input[i]);
		else
		{
			
			setIterator iterGreatest=leastnumbers.begin();
			if(input[i]<*iterGreatest)
			{
				leastnumbers.erase(iterGreatest);
				leastnumbers.insert(input[i]);
			}
		}
	}
}

int main()
{
	int input[]={4,5,1,6,2,7,3,8,3};
	int k;
	intset myset;
	cin>>k;
	getleastnumbers(input,9,myset,k);
	for(setIterator it=myset.begin();it!=myset.end();++it)
		cout<<*it<<" ";
	cout<<endl;
	return 1;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值