1. 题目描述
请设计一个复杂度为O(n)的算法,计算一个未排序数组中排序后相邻元素的最大差值。
给定一个整数数组A和数组的大小n,请返回最大差值。保证数组元素个数大于等于2小于等于500。
测试样例:
- 输入: [9,3,1,10],4
- 输出:返回:6
2. 思路
-
首先求出数组的最大值max和最小值min;
-
然后将该区间均等的划分为n+1份,即n+1个桶,那么由于只有n个数,因此,必定至少有一个桶为空桶;
-
遍历数组,将所有数入桶,并记录每一个桶的最大值和最小值;
-
不用考虑桶内数的差值,因为它都不会大过空桶两边的桶的数的差值;
-
依次遍历每一个桶,找到一个空桶,记录其前一个非空桶的最大值和其后一个非空桶的最小值,它们的差值就是最大的(考虑有多个空桶的情况)。
3. Code
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
class MaxDivision {
public:
static int bucket(int num, int length, int min, int max) {
return (num - min) * length / (max - min);
}
int findMaxDivision(vector<int> vec, int n) { // n是所有元素的个数
// write code here
int min = INT_MAX;
int max = INT_MIN;
if (n < 2) { // 如果没有元素或者只有一个元素的话那么相邻的最小值就是0
return 0;
}
for (int i = 0; i < n; ++i) { // 求出整个vec的最小值和最大值
min = std::min(vec[i], min);
max = std::max(vec[i], max);
}
if (min == max) { // 表示所有元素都是一样的哈
return 0;
}
std::vector<bool> hasNum (n + 1, false); // 首先首先使用N+1保存是否桶有元素
std::vector<int> mins (n + 1, -1); // 记录每一个桶的最小值
std::vector<int> maxs (n + 1, -1); // 记录每一个桶的最大值
int bid = 0; // 当前元素所属于哪个桶
for (int i = 0; i < n; ++i) {
bid = bucket(vec[i], n, min, max); // 计算当前属于哪个桶
mins[bid] = hasNum[bid] ? std::min(vec[i], mins[bid]) : vec[i];
maxs[bid] = hasNum[bid] ? std::max(vec[i], maxs[bid]) : vec[i];
hasNum[bid] = true;
} // 保留每一个桶里面的最大值最小值
int res = 0;
int i = 1;
int lastMax = maxs[0]; // 思想是当前的非空桶最小值减去前一个非空桶最大值
for (; i <= n; ++i) { // 总共N+1桶,我们从1开始循环到N
if (hasNum[i]) { // 当前桶为非空桶
res = std::max(mins[i] - lastMax, res); // 计算每一轮的最大值
lastMax = maxs[i];
}
}
std::vector<bool>().swap(hasNum);
std::vector<int>().swap(mins);
std::vector<int>().swap(maxs);
return res;
}
};