方法一(位图法):
- 遍历原数组,求出最大值Max和最小值Min;
- 创建一个长度为k(k=Max-Min+1)的新数组Array;
- 遍历原数组,把原数组每一个元素插入到新数组Array对应的位置,比如元素的值为n,则插入到Array[n-min]当中。此时Array的部分位置为空,部分位置填充了数值。
- 遍历新数组Array,统计出Array中最大连续出现空值的次数+1,即为相邻元素最大差值。
** 缺点:当数组中元素悬殊很大时,如1、2、100000000,则需要构造一个长度是100000000的新数组Array,则该方法不可取。**
方法二(桶排序):
假设原数组长度为N
- 遍历原数组,求出最大值Max和最小值Min;
- 将最小值Min与最大值Max所界定的区间划分成N+1个桶,每个桶的区间长度为d=(Max-Min)/N;
- 创建一个长度是N+1的数组Array,数组中的个元素是List,代表一个桶;
这样每个桶的区间范围:[Min, Min+d)、[Min+d, Min+2d)、[Min+2d, Min+3d)、…、[Min+(N-1)d, Min+Nd=Max)、[Min+Nd=Max, Min+Nd=Max]
- 遍历原数组,把原数组中的每一个元素插入到新数组Array对应的桶当中,进入各个桶的条件是根据不同的数值区间;
由于桶的总数量是N+1,故至少有一个桶是空的,且空桶肯定不是第一个(至少有Min)和最后一个桶(有Max)。
最大差值肯定出现在空桶附近。(非空桶内部最大差值<d,空桶左边第一个非空桶的最大值 与 空桶右边第一个非空桶的最小值 > d)
- 遍历新数组Array,计算每一个空桶右端非空桶中的最小值,与空桶左端非空桶的最大值的差。数值最大的差即为原数组排序后的相邻最大差值。
空间复杂度:O(N),时间复杂度:O(N)(总共扫描3次)。
实现
int maxGap(std::vector<int> &vecNum)
{
// 获取最大值与最小值
int nMax = vecNum[0], nMin = vecNum[0];
for (int nIndex = 1; nIndex < vecNum.size(); nIndex++)
{
if (nMax < vecNum[nIndex])
{
nMax = vecNum[nIndex];
}
else if (nMin > vecNum[nIndex])
{
nMin = vecNum[nIndex];
}
}
// 桶的个数
int nBucketNum = vecNum.size() + 1;
// 每个桶的区间长度
int nBucketLength = (nMax - nMin) / vecNum.size();
// 记录桶的最小值
std::vector<int> vecBucketMin(nBucketNum, INT_MAX);
// 记录桶的最大值
std::vector<int> vecBucketMax(nBucketNum, INT_MIN);
// 获取每个桶内的最小和最大值
for (int nIndex = 0; nIndex < vecNum.size(); nIndex++)
{
// 映射到某一个桶
int nBucketIndex = (vecNum[nIndex] - nMin) / nBucketLength;
// 记录桶的最大和最小值
if (vecBucketMax[nBucketIndex] < vecNum[nIndex])
{
vecBucketMax[nBucketIndex] = vecNum[nIndex];
}
if (vecBucketMin[nBucketIndex] > vecNum[nIndex])
{
vecBucketMin[nBucketIndex] = vecNum[nIndex];
}
}
// 计算每一个空桶右端非空桶中的最小值,与空桶左端非空桶的最大值的差
int nMaxGap = 0;
int nPreMax = vecBucketMax[0];
bool nEmptyBucket = false;
for (int nBucketIndex = 1; nBucketIndex < nBucketNum; nBucketIndex++)
{
if (vecBucketMin[nBucketIndex] != INT_MAX)
{
// 非空桶
if (nEmptyBucket)
{
// 前一个是空桶
nMaxGap = vecBucketMin[nBucketIndex] - nPreMax;
}
nPreMax = vecBucketMax[nBucketIndex];
nEmptyBucket = false;
}
else
{
// 空桶
nEmptyBucket = true;
}
}
return nMaxGap;
}