这是一道微软的面试题,原题是这样的:
有一个整数数组,请求出两两之差绝对值最小的值,记住,只要得出最小值即可,不需要求出是哪两个数。(复杂度N^2则不得分)
解法一:看到这个这个题目第一个念头就是暴力解法,通过两个for循环两两相减,记录最小值即可:
int func(int* arr,int n)
{
int nmin = abs(arr[0]-arr[1]);
for(int i = 0; i < n-1; i++)
{
for(int j = i+1; j < n; j++)
{
int d = abs(arr[i]-arr[j]);
if(d<nmin) nmin = d;
}
}
return nmin;
}
这样对于我们来说肯定是最方便的也是最容易实现的,但是这样不符合要求,因为这个解法复杂度不符合要求。
解法二:先排序再查找相邻两个元素只差的绝对值,使用快速排序算法,复杂度可以降为O(nLogn):
//快速排序
void q_sort(int* arr,int l,int r)
{
if(l>=r) return;
int low = l,high = r;
int x = arr[l];
while(low<high)
{
while(low<high && arr[high]>x) high--;
if(low<high) arr[low] = arr[high];
while(low<high && arr[low]<=x) low++;
if(low<high) arr[high] = arr[low];
}
arr[low] = x;
q_sort(arr,l,low-1);
q_sort(arr,low+1,r);
}
int func(int* arr,int n)
{
q_sort(arr,0,n-1);
int nmin = abs(arr[0]-arr[1]);
for(int i = 1; i < n-1; i++)
{
int d = abs(arr[i]-arr[i+1]);
if(d<nmin) nmin=d;
}
return nmin;
}
这个方法基本满足了题目的要求,但明显不适最好的解法,因为题目中强调并不需要求出是哪两个数,我们就假设肯定有最优解。
解法三:我们可以将问题进行一次改造,假设整数数组是a1,a2...an,我们可以通过引入辅助数组将计算任意两个元素只差转化为子段之和:
b1 = a1-a2
b2 = a2-a3
......
b(n-1) = a(n-1) - an
可以简单的推断出这样一个公式:ai - aj = bi+...+b(j-1)
这样就将问题简化为求一个整数数组的最小子段和的绝对值,也就是说子段和的绝对值最小。
还没有想出来......如果谁想出来了希望能够告诉我......