数组排序之后相邻数的最大差值
题目
给定一个整型数组arr,返回如果排序之后,相邻两数的最大差值。
arr=[9,3,1,10]。如果排序,结果为[1,3,9,10],9和3的差为最大差值,故返回6。
arr=[5,5,5,5]。返回0。
如果arr的长度为N,请做到时间复杂度为O(N)。
思路
如果用排序做,最好的是O(n*log(n))
利用桶排的思想
比如有10个数,最小是10,最大是110,那么就化为11个区间,最后一个区间是最后一个数
其余区间就是[10,20),[20,30),[30,40)…[90,100),[100,110)
然后把这10个数字放到11个区间里去,那么必然有一个区间是空的
而最大差值是一个非空区间最大值与另一个非空区间最小值得差,(两者中间可能有空区间)
因为同一区间内的差值最大是就是间隔
因此需要先找到最大值和最小值,然后划分区间,把数字放到区间中去,找最大差值
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| public int maxGap(int[] a) { if (a.length == 0 || a == null) { return 0; } // 求出最大最小值 int min = Integer.MAX_VALUE; int max = Integer.MIN_VALUE; for (int i = 0; i < a.length; i++) { min = Math.min(a[i], min); max = Math.max(a[i], max); } if (max == min) { // 最大值与最小值相等,说明所有数字都相等,差值为0 return 0; } // 记录每个桶的最大值和最小值,及该桶是否有值 int[] minb = new int[a.length + 1]; int[] maxb = new int[a.length + 1]; boolean[] is = new boolean[a.length + 1]; int len = a.length; for (int i = 0; i < len; i++) { // 找到该数应该放在哪个桶里 int bid = bucket(a[i], min, max, len); if (is[bid]) { minb[bid] = Math.min(a[i], minb[bid]); maxb[bid] = Math.max(a[i], maxb[bid]); } else { minb[bid] = a[i]; maxb[bid] = a[i]; is[bid] = true; } } int i = 0; //计算结果时候的前区间的最大值 int num = 0; //最大差值,即后最小减前最大 int res = 0; //找到第一个不空的区间 while (i < len) { if (is[i]) { num = maxb[i]; i++; break; } } //找到后面不空的区间 for (; i <= len; i++) { if (is[i]) { res = Math.max(res, minb[i] - num); //每次重置前区间的最大值 num = maxb[i]; } } return res; } //找到数字i在哪个哪个区间中! //((i - min) * len / (max - min)) //用long是为了防止溢出 public int bucket(long i, long min, long max, long len) { return (int) ((i - min) * len / (max - min)); }
|