1.leetcode链接(hard)
2. 题目描述
给定未排序的数组,找到其排序形式中的连续元素之间的最大差异。
如果数组包含少于2个元素,则返回0。
Case example:
Input: [3,6,9,1]
Output: 3
Explanation: 排序后是[1,3,6,9],
(3,6)或(6,9) 有最大差3.
3.思路分析
复杂度分析
如果使用普通的排序,时间复杂度nlogn。
建议使用桶排序的思想。时间和空间复杂度都是O(n)。
思路分析
假设nums中的所有n个元素都在[minNum,maxNum]内,最大间隔不会小于gap =(maxNum - minNum)/(n - 1)。 但是,这个间隔可能会为0,因此我们将其最大值设为1,以保证用于创建存储桶的间隔是有意义的。
然后最多将有m =(maxNum-minNum)/ gap + 1个桶。 对于每个数字num,它将落在k =(num-minNum)/ gap 这个bucket中。 将所有nums元素放入相应的存储桶后,我们只需扫描存储桶即可计算最大间隔。
最大间隔仅取决于当前桶的最大值和下一个相邻桶的最小值(桶不应为空)。 所以我们只存储每个桶的最小值和最大值。 每个存储区初始化为{minimum = INT_MAX,maximum = INT_MIN},然后在更新存储区时进行更新。
实现分析
1.遍历nums,得出其最大最小值;
2.求得间隔;
3.遍历nums,将符合要求的值放入相应桶中,只需保留每个桶的最大/最小值;
4.遍历得到最大差。
4.C++代码
class Solution {
public:
int maximumGap(vector<int>& nums) {
int n=nums.size();
if(n<=1){
return 0;
}
//遍历1次,得出最大/最小值
int maxNum=nums[0];
int minNum=nums[0];
for(int i=1;i<nums.size();i++){
if(nums[i]>maxNum){
maxNum=nums[i];
}
else if(nums[i]<minNum){
minNum=nums[i];
}
}
int gap=(maxNum-minNum)/(nums.size()-1);
if(gap<1) {
gap = 1;
}
//m表示桶的数量
int m=(maxNum-minNum)/gap+1;
//桶的最大值和最小值数组
vector<int> bucketsMin(m,INT_MAX);
vector<int> bucketsMax(m,INT_MIN);
//遍历,将数字放入相应的桶,只需保留每个桶的最大/最小值
for(int i=0;i<nums.size();i++){
int k=(nums[i]-minNum)/gap;
if(nums[i]<bucketsMin[k]) bucketsMin[k]=nums[i];
if(nums[i]>bucketsMax[k]) bucketsMax[k]=nums[i];
}
int i=0,j;
gap=bucketsMax[0]-bucketsMin[0];
while(i<m){
j=i+1;
//遇到空桶,j++
while(j<m&&bucketsMin[j]==INT_MAX&&bucketsMax[j]==INT_MIN)
j++;
if(j==m) break;
//gap为右边桶j的最小值与左边桶i的最大值的差与之前gap的较大者
gap=max(gap,bucketsMin[j]-bucketsMax[i]);
i=j;
}
return gap;
}
};
5.调试
前面添加头文件
#include <iostream>
#include <vector>
using namespace std;
后面添加测试代码即可
int main(){
Solution s;
vector<int> nums={3,6,9,1};
cout<<s.maximumGap(nums)<<endl;
return 0;
}
//result:3
参考资料
https://leetcode.com/problems/maximum-gap/discuss/50694/12ms-C%2B%2B-Suggested-Solution