给定一个数组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;
}原文地址:http://blog.csdn.net/acvcla/article/details/43085751