You have k lists of sorted integers in non-decreasing order. Find the smallest range that includes at least one number from each of the k lists.

We define the range [a, b] is smaller than range [c, d] if b - a < d - c or a < c if b - a == d - c.

solution

merge k lists + sliding window

def smallestRange(self, nums: List[List[int]]) -> List[int]:
	def merge():
	merged = []
	minheap = [(nums[k][0], k, 0) for k in range(len(nums))]
	heapify(minheap)
	  
	while minheap:
		val, list_id, list_idx = heappop(minheap)
		merged.append((val, list_id))
		if list_idx+1 < len(nums[list_id]):
			heappush(
				minheap,
				(nums[list_id][list_idx+1], list_id, list_idx+1)
			)
		return merged
 
	merged = merge()
	  
	# sliding window
	best = inf
	res = []
	# counts per list_id
	counts = defaultdict(int)
	# list id's currently in window
	seen = set()
	l = 0
	for r in range(len(merged)):
		val, list_id = merged[r]
 
		# add merged[r] to window
		counts[list_id] += 1
		if counts[list_id] == 1:
			seen.add(list_id)
 
		# slide window up left until invalid
		while len(seen) == len(nums):
			if merged[r][0]-merged[l][0] < best:
				res = [merged[l][0], merged[r][0]]
				best = merged[r][0]-merged[l][0]
 
			_, remove_list_id = merged[l]
			counts[remove_list_id] -= 1
			if counts[remove_list_id] == 0:
				seen.remove(remove_list_id)
			l += 1
 
	return res