给定一个数组,求如果排序之后,相邻两数的最大差值,要求时间复杂度O(N),且要求不能用非基于比较的排序。
解题
1.已知数组长度为 N
2.遍历数组,找到整个数组中元素的最大值 max 和最小值 min
3.最小值放入0号桶,最大值放入N+1号桶
根据找到的 max 和 min,将数组均匀划分为 n + 1 个范围。
4.遍历数组,根据每个数组元素的值,判断需要进入哪个桶,最后找到每个桶中的最大值和最小值。
5.遍历数组 用该数组的最小值-前一个非空桶的最大值,更新全局Max(最大差值)
设立N+1个桶的目的 是因为必定会有一个空桶,那么最大差值就不会出席现在一个桶中 而且空桶前后不一定是最大差值
#include <iostream>
#include <cstring>
using namespace std;
const int N = 100010;
bool IsVisit[N+1];//判断一个桶是不是空桶
int MinNum[N+1];//记录一个桶的最小值
int MaxNum[N+1];//记录一个桶的最大值
int Arr[N];//原数组
int FindPos(int nNum, int nMin, int nMax, int nLen);
//返回一个数 应该放入哪个桶
void PutInBucket(int nLen, int nMax, int nMin);//把所有的数放入桶里
int GetMax(int nLen);//返回最大的差值
int main(int argc, char** argv)
{
int nMin = 0x3f3f3f3f;
int nMax = -2e9;
memset(MaxNum,-2e9,sizeof(MaxNum));
memset(MinNum,0x3f3f3f3f,sizeof(MinNum));
//输入这个数组的长度
int nLen;
scanf("%d",&nLen);
//数组的赋值 并且求出这个数组的最大值和最小值
for(int i = 0; i < nLen; i++)
{
scanf("%d",&Arr[i]);
nMin = min(nMin,Arr[i]);
nMax = max(nMax,Arr[i]);
}
//数组中元素的值相等 最大差值0
if(nMin == nMax)
{
return 0;
}
PutInBucket(nLen, nMax, nMin);
cout<<GetMax(nLen)<<endl;;
return 0;
}
int FindPos(long nNum, long nMin, long nMax, long nLen)
{
return (int) (nNum-nMin) * nLen / (nMax-nMin);
}
void PutInBucket(int nLen, int nMax, int nMin)
{
for(int i = 0; i < nLen; i++)
{
int nNum = Arr[i];
int nPos =
FindPos((long)nNum, (long)nMin, (long)nMax, (long)nLen);
//如果这个桶没有被访问过
if(!IsVisit[nPos])
{
MaxNum[nPos] = nNum; MinNum[nPos] = nNum;
IsVisit[nPos] = true;
}
else
{
MaxNum[nPos] =
nNum > MaxNum[nPos] ? nNum : MaxNum[nPos];
MinNum[nPos] =
nNum < MinNum[nPos] ? nNum : MinNum[nPos];
}
}
}
int GetMax(int nLen)
{
int nRes = 0;//记录最大差值
int nLastMaxPos = 0;//记录上一个非空桶的位置
//注意此处 是遍历N+1个桶
for(int i = 0; i <= nLen; i++)
{
//这个桶不是空桶
if(IsVisit[i])
{
nRes = max(nRes, MinNum[i] - MaxNum[nLastMaxPos]);
nLastMaxPos = i;
}
}
return nRes;
}