给定一个数组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:[email protected] > Mail: [email protected] > 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; }
时间: 2024-10-01 05:14:40