Similar Problems
Similar Problems not available
Smallest Range Covering Elements From K Lists - Leetcode Solution
Companies:
LeetCode: Smallest Range Covering Elements From K Lists Leetcode Solution
Difficulty: Hard
Topics: greedy hash-table sliding-window heap-priority-queue array sorting
Problem statement:
You have k lists of sorted integers in non-decreasing order. You want to find the smallest range that includes at least one number from each of the k lists.
Solution:
Approach:
We can solve this problem using a sliding window technique. We’ll start with a window of size k with the first element of each list in it. Then we’ll move the right pointer of the window to find the range that includes at least one element from each list. Once we do this, we can move the left pointer to see if there’s a smaller range that still includes at least one element from each list.
Let’s walk through an example to understand this approach.
Example:
Consider the following lists:
A: [4, 10, 15, 24, 26] B: [0, 9, 12, 20] C: [5, 18, 22, 30]
Initially, our window will be [4,0,5]. We can find the smallest range that includes at least one element from each list by moving the right pointer until we cover all the lists:
[4,0,5], [10,0,5], [10,9,5], [15,9,5], [15,12,5], [15,18,5], [24,18,5], [24,20,5], [26,20,5], [26,22,5], [26,22,30]
The smallest range is [20,24] which covers the elements {24,20,22}.
Now we can move the left pointer to see if there’s a smaller range that still includes at least one element from each list. If the left pointer is at A[0], then the range will include A[1], so we can move the left pointer to A[1] and check if we can find a smaller range. Repeating this process, we can find the smallest range that includes at least one element from each list.
Implementation:
To implement this approach, we’ll use a priority queue to keep track of the current maximum element in each list. We’ll start with a window of size k with the first element of each list in it. Then, we’ll move the right pointer until we cover all the lists. Once we do this, we’ll move the left pointer until we can’t reduce the range any further. We’ll keep track of the smallest range we encounter along the way.
Here’s the code:
class Solution:
def smallestRange(self, nums: List[List[int]]) -> List[int]:
left, right = 0, 0
n = len(nums)
heap = [(nums[i][0], i) for i in range(n)]
heapq.heapify(heap)
max_elem = max(heap)[0]
range_start, range_end = float('-inf'), float('inf')
while True:
# Move right pointer until we cover all the lists
if right == len(nums[0]):
break
while heap:
elem, idx = heapq.heappop(heap)
if elem > max_elem:
max_elem = elem
if right - idx < range_end - range_start:
range_start, range_end = idx, right
if idx + 1 < len(nums[idx]):
heapq.heappush(heap, (nums[idx + 1][idx + 1], idx + 1))
else:
break
# Move left pointer to see if there's a smaller range that still includes at least one element from each list
if len(heap) == n:
left_elem, left_idx = heapq.heappop(heap)
if right - left_idx < range_end - range_start:
range_start, range_end = left_idx, right
heapq.heappush(heap, (nums[left_idx][left_elem], left_idx))
max_elem = max(max_elem, nums[left_idx][left_elem])
left += 1
else:
break
right += 1
return [nums[i][j] for i in range(n) for j in range(range_start, range_end + 1)]
Time Complexity:
The time complexity of this algorithm is O(n * k * log(n)) where n is the number of lists and k is the maximum length of a list. This is because we need to iterate over all the elements in all the lists, and we need to use a priority queue to keep track of the maximum element in all the lists, which requires log(n) time for insertion and removal.
Space Complexity:
The space complexity of this algorithm is O(n) because we need to store the maximum element in each list in a priority queue.
Smallest Range Covering Elements From K Lists Solution Code
1