问题:
你有 k 个 非递减排列 的整数列表。找到一个 最小 区间,使得 k 个列表中的每个列表至少有一个数包含在其中。
我们定义如果 b-a < d-c 或者在 b-a == d-c 时 a < c,则区间 [a,b] 比 [c,d] 小。
示例
输入:nums = [[4,10,15,24,26], [0,9,12,20], [5,18,22,30]]
输出:[20,24]
解释:
列表 1:[4, 10, 15, 24, 26],24 在区间 [20,24] 中。
列表 2:[0, 9, 12, 20],20 在区间 [20,24] 中。
列表 3:[5, 18, 22, 30],22 在区间 [20,24] 中。
思想
排序加滑动窗口来解决这个问题,利用go语言自带的map记录每个区间的值并且区间的值做键,区间索引做值,这样避免重复并且保存区间的最小值和最大值。在定义left左边界索引,right为右边界索引。在这个区间中遍历,直到找到最小区间为止。
代码
func smallestRange(nums [][]int) []int {
size :=len(nums)
hashMap := map[int][]int{}
xMin, xMax := math.MaxInt32, math.MinInt32
for i :=0 ;i < size; i++ {
for _,x := range nums[i] {
hashMap[x] = append(hashMap[x],i)
xMin = min(xMin,x)
xMax = max(xMax,x)
}
}
left,right := xMin, xMin-1
inSide := 0
indicate := make([]int, size)
bestLeft,bestRight := xMin, xMax
for right < xMax {
right++
if len(hashMap[right]) > 0 {
for _,x := range hashMap[right] {
indicate[x]++
if indicate[x] == 1 {
inSide++
}
}
for inSide == size {
if bestRight - bestLeft > right - left {
bestRight = right
bestLeft = left
}
for _,x := range hashMap[left]{
indicate[x]--
if indicate[x] == 0{
inSide--
}
}
left++
}
}
}
ans := []int{bestLeft,bestRight}
return ans
}
func min(x int, y int ) int {
if x > y{
return y
}
return x
}
func max(x int, y int) int {
if x > y{
return x
}
return y
}