2021-05-20:给定一个数组arr, 返回如果排序之后,相邻两数的最大差值。要求:时间复杂度O(N) 。
福大大 答案2021-05-20:
假设答案法。N个数,根据最大值和最小值的范围等分成N+1个桶。每个桶只需要存当前桶的最大值和最小值。根据鸽笼原理,必然存在空桶。最后只需要遍历求【右桶min-左桶max】,返回最大值。最终答案可能来自相邻桶(这个很难想到),也可能来自跨桶(空桶的左侧和右侧就是跨桶),但是一定不会来自同一个桶内部的情况。另外,这道题是以空间复杂度换取时间复杂度
代码用golang编写。代码如下:
package main import ( "fmt" "math" ) func main() { arr := []int{17, 13, 15, 0, 49, 47, 43, 99, 84} ret := maxGap(arr) fmt.Println(ret) } func maxGap(nums []int) int { if len(nums) < 2 { return 0 } N := len(nums) min := math.MaxInt64 max := math.MinInt64 for i := 0; i < N; i++ { min = getMin(min, nums[i]) max = getMax(max, nums[i]) } if min == max { return 0 } // 不止一种数,min~max一定有range, len个数据,准备len+1个桶 hasNum := make([]bool, N+1) // hasNum[i] i号桶是否进来过数字 maxs := make([]int, N+1) // maxs[i] i号桶收集的所有数字的最大值 mins := make([]int, N+1) // mins[i] i号桶收集的所有数字的最小值 bid := 0 // 桶号 for i := 0; i < N; i++ { bid = bucket(nums[i], N, min, max) mins[bid] = twoSelectOne(hasNum[bid], getMin(mins[bid], nums[i]), nums[i]) maxs[bid] = twoSelectOne(hasNum[bid], getMax(maxs[bid], nums[i]), nums[i]) hasNum[bid] = true } res := 0 lastMax := maxs[0] // 上一个非空桶的最大值 i := 1 for ; i <= N; i++ { if hasNum[i] { res = getMax(res, mins[i]-lastMax) lastMax = maxs[i] } } return res } // 如果当前的数是num,整个范围是min~max,分成了len + 1份 // 返回num该进第几号桶 func bucket(num int, N int, min int, max int) int { return (num - min) * N / (max - min) } func getMin(a int, b int) int { if a < b { return a } else { return b } } func getMax(a int, b int) int { if a > b { return a } else { return b } } func twoSelectOne(c bool, a int, b int) int { if c { return a } else { return b } }
执行结果如下: