排序数组中的相邻两数最大差值

xiaoxiao2021-02-28  64

给定一个数组A及其大小n,求其排序后的相邻两数的最大差值。(注:要求时间复杂度为O(n))

思路:题目要求对排序后的数组进行操作,显然需要先对数组进行排序。如果没有要求时间复杂度,那么可以有很多种排序算法,如快速排序、堆排序、归并排序等等。但是这里要求时间复杂度为O(n),就不能用上述常规的排序算法了。

那么桶排序可以吗?由于我们不知道最大数的位数,因此,如果最大数的位数很大的话,我们就需要成千上万个桶,显然对空间要求太大。我们可以利用桶排序的思想,利用它的变种:

1) 首先求出数组的最大值max和最小值min;

2) 然后将该区间均等的划分为n+1份,即n+1个桶,那么由于只有n个数,因此,必定至少有一个桶为空桶;

3) 遍历数组,将所有数入桶,并记录每一个桶的最大值和最小值;

4) 不用考虑桶内数的差值,因为它都不会大过空桶两边的桶的数的差值;

5) 依次遍历每一个桶,找到一个空桶,记录其前一个非空桶的最大值和其后一个非空桶的最小值,它们的差值就是最大的(考虑有多个空桶的情况)。

code:

int maxGap(int A[], int n) { int min = A[0]; int max = A[0]; //找出最大值和最小值 for(int i = 1; i < n; ++i){ min = (min <= A[i] ? min : A[i]); max = (max >= A[i] ? max : A[i]); } int* minArr = new int[n+1]();//记录每个桶中的最小数 int* maxArr = new int[n+1]();//记录每个桶中的最大数 bool hasNum[n+1] = {0};//记录桶中是否有数 for(int i = 0; i < n; ++i){ //求出每一个数所在的桶的编号 int bocketID = bocketNum(a, i, min, max, n); minArr[bocketID] = hasNum[bocketID] ? Min(minArr[bocketID], A[i]) : A[i]; maxArr[bocketID] = hasNum[bocketID] ? Max(maxArr[bocketID], A[i]) : A[i]; hasNum[bocketID] = true; } int MaxGap = 0;//记录最大差值 int LastMax = 0;//记录当前空桶的上一个桶的最大值 int i = 0; while(i < n + 1){ //可能会有多个空桶 //遍历桶,找到一个空桶 while(i < n + 1 && hasNum[i]) i++; if(i == n + 1) break; LastMax = maxArr[i-1]; //继续遍历桶,找到下一个非空桶 while(i < n + 1 && !hasNum[i]) i++; if(i == n + 1) break; MaxGap = Max(MaxGap, minArr[i]-LastMax); } delete []minArr; delete []maxArr; return MaxGap; } //求出每一个数所在的桶的编号 int bocketNum(int a[], int i, int min, int max, int len){ return (a[i]-min) * len / (max-min); } int Min(int a, int b){ return a <= b ? a : b; } int Max(int a, int b){ return a >= b ? a : b; }

转载请注明原文地址: https://www.6miu.com/read-76093.html

最新回复(0)