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

给定一个数组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

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

找出数组中差值为k去重后的数对

思路:已知一个含有重复数字的无序数组,还有一个整数k,找出有多少对不重复的数对(i, j)使得i和j的差刚好为k.由于k有可能为0,而只有含有至少两个相同的数字才能形成数对,那么就是说需要统计数组中每个数字的个数.可以建立每个数字和其出现次数之间的映射,然后遍历哈希表中的数字,如果k为0且该数字出现的次数大于1,则结果count自增1:如果k不为0,且用当前数字加上k后得到的新数字也在数组中存在,则结果count自增1,参见代码如下: class Solution { public: int f

算法题:找出一个数组中相加值最大的连续序列元素

package arithmetic; /** * @author SHI * 求一个数组中相加值最大的连续序列元素 */ public class MaxSequence { public static void main(String[] args) { int[] a=new int[]{-2,9,-3,4,-6,7,-6,4}; findBigSequence(a); } /** * 思想: (1)计算出该数组的所有元素和,假设该值为最大 * (2)从数组下标1到a.length-1依次

找一个数组中第K大的数

快排思想,选取序列的一个key进行划分,小于key的分在左边,大于key的在右边,key的位置-low+1就是最后一个元素是key的序列中元素的数量,当元素数量大于K时,就在左半部分递归找,等于时 arr[key]就是第K 大的元素,小于K时,在右边递归找第k-num大的元素 /** * 文件名:FindK.java * 时间:2014年11月7日上午11:23:43 * 作者:修维康 */ package chapter7; /** * 类名:FindK 说明:找到一个数组中第K大的元素 */

删除一个数组中某个值

#include<stdio.h> int tab[10]={0,1,2,3,5,5,5,7,7,9}; void deleteMember(int mem){     int i = 0;     int j = 0;     for(i = 0, j = 0; i < (sizeof(tab)/sizeof(int)); i++){         if(tab[i] != mem){             tab[j++] = tab[i]         }     }    

PHP usort 使用用户自定义的比较函数对数组中的值进行排序

From: http://www.php100.com/cover/php/2395.html usort (PHP 4, PHP 5) usort — 使用用户自定义的比较函数对数组中的值进行排序 说明 bool usort ( array &$array , callback $cmp_function ) 本函数将用用户自定义的比较函数对一个数组中的值进行排序.如果要排序的数组需要用一种不寻常的标准进行排序,那么应该使用此函数. 比较函数必须在第一个参数被认为小于,等于或大于第二个参数时分

PHP 使用用户自定义的比较函数对数组中的值进行排序

原文:PHP 使用用户自定义的比较函数对数组中的值进行排序 usort (PHP 4, PHP 5) usort —      使用用户自定义的比较函数对数组中的值进行排序 说明 bool usort        ( array &$array       , callable $cmp_function       ) 本函数将用用户自定义的比较函数对一个数组中的值进行排序.如果要排序的数组需要用一种不寻常的标准进行排序,那么应该使用此函数. Note: 如果两个成员比较结果相同,则它们在排

程序员面试100题之十:快速找出一个数组中的两个数字,让这两个数字之和等于一个给定的值(转)

能否快速找出一个数组中的两个数字,让这两个数字之和等于一个给定的值,为了简化起见,我们假设这个数组中肯定存在至少一组符合要求的解. 假如有如下的两个数组,如图所示: 5,6,1,4,7,9,8 给定Sum= 10 1,5,6,7,8,9 给定Sum= 10 分析与解法 这个题目不是很难,也很容易理解.但是要得出高效率的解法,还是需要一番思考的. 解法一 一个直接的解法就是穷举:从数组中任意取出两个数字,计算两者之和是否为给定的数字. 显然其时间复杂度为N(N-1)/2即O(N^2).这个算法很简

阿里 2014-08-29 校招机试题 求一个存放整数的二叉树相差最大的两节点差值绝对值

题目:写一个函数,输入一个二叉树,树中每个节点存放了一个整数值,函数返回这颗二叉树中相差最大的两个节点间的差值绝对值.请注意程序效率. 如果是数值之差,感觉怎么着也得遍历一遍,直接修改下二叉树的基本遍历代码就可以. #include<stdio.h> #include <stdlib.h> typedef struct Node { int data; struct Node * left; struct Node * right; } BitNode, *BiTree; /* 求

求二叉树中相差最大的两个节点间的差值绝对值

题目描述: 写一个函数,输入一个二叉树,树中每个节点存放了一个整数值,函数返回这棵二叉树中相差最大的两个节点间的差值绝对值.请注意程序效率. solution: int findMinMax(BTNode *T) { if(!T) return 0; int max = INT_MIN; int min = INT_MAX; stack<BTNode*> s; s.push(T); while (!s.empty()) { BTNode *tmp = s.top(); if(tmp->d