/************************************************************************/
/* 1、有一个整数数组,求出两两只差绝对值最小 */
/************************************************************************/
int iCompare(const void* lhs, const void* rhs)
{
return *(const int *)lhs - *(const int *)rhs;
}
//使用快速排序的方法,时间复杂度O(nlogn), 空间O(1)
int minSubBySort(int *iArr, int length)
{
if(!iArr || length < 2)
throw new exception("error");
//从小到大排序
qsort(iArr, length, sizeof(int), iCompare);
//遍历求解最小差值
int minSub = numeric_limits<int>::max();
for(int i = 0; i < length - 1; ++i)
{
int curSub = iArr[i + 1] - iArr[i];
if(minSub > curSub)
minSub = curSub;
}
return minSub;
}
void insertSort(vector<int>& ivect)
{
for(unsigned i = 1; i < ivect.size() ; ++i)
{
for(int j = i - 1; j >= 0; --j)
{
if(ivect[j + 1] < ivect[j])
{
int temp = ivect[j + 1];
ivect[j + 1] = ivect[j];
ivect[j] = ivect[j + 1];
}
else
break;
}
}
}
//快速排序换成桶排序时间O(n), 空间O(n)
int minSubByBucketSort1(int * arr, int length)
{
//一共length个桶, 每个桶步长为h = maxSub / (length - 1), [min, min + h), [min + h, m + 2h)...
// 找打最大最小元素
int minVal = arr[0];
int maxVal = arr[0];
for(int i = 1; i < length; ++i)
{
if(arr[i] > maxVal)
maxVal = arr[i];
if(arr[i] < minVal)
minVal = arr[i];
}
//计算h
int h = (int)ceil((maxVal - minVal)/double(length -1));
//length个桶,数组中元素放入桶中
vector<int>* vectArr = new vector<int>[length];
for(int j = 0; j < length; ++j)
{
int pos = (arr[j] - minVal) / h;
vectArr[pos].push_back(arr[j]);
}
//对桶中元素排序
for(int k = 0; k < length; ++k)
{
insertSort(vectArr[k]);
}
int curMin = numeric_limits<int>::max();
int preMax = numeric_limits<int>::min();
int curMax = numeric_limits<int>::min();
int minSub = numeric_limits<int>::max();
for(int l = 0; l < length; ++l)
{
//桶间比较
if(vectArr[l].size() == 0)
break;
else
{
curMin = vectArr[l][0];
curMax = vectArr[l][vectArr[l].size() - 1];
if(preMax != numeric_limits<int>::min())
minSub = minSub < abs(curMin - preMax) ? minSub : abs(curMin - preMax);
}
//桶内比较
for(unsigned m = 0; m < vectArr[l].size() - 1; ++m)
{
int absSub = vectArr[l][m+1]- vectArr[l][m];
if( absSub < minSub)
minSub = absSub;
}
preMax = curMax;
}
//
return minSub;
}
//桶排序方法时间O(n), 空间O(2n),桶内元素不排序
//桶范围h:maxSub = max - min, h = maxSub / (n - 1), [min, min + h), [min + h, m + 2h)...
//至少有一个桶中元素数量大于2,计算每个桶中的最小差值,与相邻桶最小差值(此桶最小值 - 上桶最大值)
//比较求得minSub
bool findMinSubOfVector(const vector<int>& iVect, int& result)
{
vector<int>::const_iterator beg = iVect.begin();
if(iVect.size() < 2)
return false;
result = numeric_limits<int>::max();
while(beg != iVect.end())
{
vector<int>::const_iterator pIter = beg + 1;
while(pIter != iVect.end())
{
if(abs(*beg - * pIter) < result)
result = abs(*beg - *pIter);
++pIter;
}
++beg;
}
return true;
}
int minSubByBucketSort(int * arr, int length)
{
if(!arr || length < 2)
throw new exception("error!");
// 找打最大最小元素
int minVal = arr[0];
int maxVal = arr[0];
for(int i = 1; i < length; ++i)
{
if(arr[i] > maxVal)
maxVal = arr[i];
if(arr[i] < minVal)
minVal = arr[i];
}
//计算h
int h = (int)ceil((maxVal - minVal)/double(length -1));
//length个桶,数组中元素放入桶中
vector<int>* vectArr = new vector<int>[length];
for(int j = 0; j < length; ++j)
{
int pos = (arr[j] - minVal) / h;
vectArr[pos].push_back(arr[j]);
}
//计算每个桶的minSub,并找到最大最小值
int preMax = numeric_limits<int>::min(), curMin = numeric_limits<int>::max();
int curMax = preMax;
int minSub = numeric_limits<int>::max();
for(int k = 0; k < length; ++k)
{
if(vectArr[k].size() == 0)
continue;
//计算桶内的minSub
int tempMinSub = numeric_limits<int>::max();
if(findMinSubOfVector(vectArr[k], tempMinSub) && minSub > tempMinSub)
minSub = tempMinSub;
//当前桶最小值和最大值
vector<int>::iterator beg = vectArr[k].begin();
curMax = *beg;
curMin = *beg;
while(beg != vectArr[k].end())
{
if(curMax < *beg)
curMax = *beg;
if(curMin > *beg)
curMin = *beg;
++beg;
}
//桶间最大最小值
if(k > 0)
{
tempMinSub = curMin - preMax;
if(minSub > tempMinSub)
minSub = tempMinSub;
}
preMax = curMax;
}
delete[] vectArr;
return minSub;
}
void testofGetMinSub()
{
const int size = 100000;
int arr[size];
//随机生成size不同的数
int rangle = size * 10;
int selected = 0;
for(int i = 0; i < rangle && selected < size; ++i)
{
if(rand() % (rangle - i) < size - selected)
arr[selected++] = i;
}
//showArr(arr, size);
DWORD start = GetTickCount();
cout << "minsub = " << minSubBySort(arr, size) << endl;
DWORD end = GetTickCount();
cout << end - start << endl;
start = GetTickCount();
cout << "minsub = " << minSubByBucketSort(arr, size) << endl;
end = GetTickCount();
cout << end - start << endl;
start = GetTickCount();
cout << "minsub = " << minSubByBucketSort1(arr, size) << endl;
end = GetTickCount();
cout << end - start << endl;
}