首页 > 代码库 > 找一个数组中差值绝对值的最小值(鸽巢原理)

找一个数组中差值绝对值的最小值(鸽巢原理)

给定一个数组a[n],要你求出数组中最小的|a[i]-a[j]|如果只有一个元素就返回0。

貌似是微软的面试题,估计大多数人首先想到的就是排序之后再比较吧,呵呵,是个人都会做。那面试官考你这个问题有毛线意义,这题我们可以用抽屉原理(也叫鸽巢原理)将n个元素放到n+1个桶中(只需要O(n)时间)。按如下过程求解:

1首先找出数组中最大的和最小的元素,如果相等,直接返回0

2确定每个桶的大小bucket_size=(maxe-mine)/(n-1)

3将每个元素放到对应的桶id bucket_id=(a[i]-mine)/bucket_size;

4最小值肯定是相邻元素相减啊,遍历一下桶,ans=min(ans,min(bucket[i]的最小值,bucket[i+1].mine-bucket[i].maxe))当然对于桶里只有一个元素的最小值肯定不用计算啦,所以我们每次可以丢掉桶里元素少于2的桶,一旦发现ans等于0之后可以立马返回啦。

代码如下:

/************************************************************************* 
    > File Name: xiaozhao.cpp 
    > Author: acvcla 
    > QQ:acvcla@gmail.com  
    > Mail: acvcla@gmail.com
    > Created Time: 2014年12月27日 星期一 22时34分13秒 
*************************************************************************/  
#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
struct Info
{
	int maxe,mine;
	vector<int>v;
	Info():maxe(-inf),mine(inf){v.clear();}
};
int find_t_min(vector<int> in) {
	int sz=in.size();
	Info bucket[sz+1];
	int maxe=*max_element(in.begin(), in.end());
	int mine=*min_element(in.begin(), in.end());
	if(maxe==mine)return 0;
	int bucket_size=(maxe-mine)/(sz-1);
	if(bucket_size==0)return 0;
	for(int i=0; i<sz; i++) {
		int bucket_id=(in[i]-mine)/bucket_size;
		bucket[bucket_id].maxe=max(bucket[bucket_id].maxe,in[i]);
		bucket[bucket_id].mine=min(bucket[bucket_id].mine,in[i]);
		bucket[bucket_id].v.push_back(in[i]);
	}
	int ans=inf;
	for(int i=0;i<sz;i++) {
		ans=min(ans,bucket[i+1].mine-bucket[i].maxe);
		if(!ans)return ans;
		if(bucket[i].v.size()>1)ans=min(ans,find_t_min(bucket[i].v));
	}
	if(bucket[sz].v.size()>1)ans=min(ans,find_t_min(bucket[sz].v));
	return ans;
}
int main(int argc, char const *argv[])
{
	int n;
	/**********************************
	*	ifstream fin("in.ini");
	*	ofstream fout("out.ini");
	*	#define cout fout
	*	#define cin fin
	**********************************/
	while(cin>>n) {
		vector<int> in;
		int x;
		while(n--) {
			cin>>x;
			in.push_back(x);
		}
		cout<<find_t_min(in)<<endl;
		in.clear();
	}
	return 0;
}

找一个数组中差值绝对值的最小值(鸽巢原理)