Solution 1: Sweepline

class Solution:
    def minAvailableDuration(self, slots1: List[List[int]], slots2: List[List[int]], duration: int) -> List[int]:
        """
        tc O((M+N)lg(M+N))
        sc  O(M+N)
        main idea: use one list to store all time slots, tracking accumulating cnt and cache previous start time 
        1. append both slots' start and end time into list with change mark 1/ 0
        2. sort by time and by start then end 
        3. each time start point, cnt + 1; otherwise cnt - 1;   
           chekc available time only when current event is end and previous cnt == 2   
        """
        l = []
        for s,e in slots1:
            l.append((s,1))
            l.append((e,0))
        for s,e in slots2:
            l.append((s,1))
            l.append((e,0))
        l.sort()
        cnt,start = 0,0
        for t,v in l:
            if v == 1:
                cnt += 1
                start = t
            else:
                if cnt == 2:
                    if t - start >= duration:
                        return [start,start+duration]
                cnt -= 1
        return []
################
class Solution:
    def minAvailableDuration(self, slots1: List[List[int]], slots2: List[List[int]], duration: int) -> List[int]:
        """
        main idea is to check accumutive sum's peek time and compare its end time with previous time 
        """
        d = defaultdict(int)
        for s,e in slots1:
            d[s] += 1
            d[e] -= 1 
        for s,e in slots2:
            d[s] += 1
            d[e] -= 1
        cnt = 0
        tm = sorted(d.items())
        prev_end = tm[0][0] 
        for t,v in tm:
            if cnt == 2 and cnt + v < 2: # here to prevent cases where two intervals totally overlaps 
                gap = t - prev_t
                if gap >= duration:
                    return [prev_t,prev_t+duration]
            cnt += v
            prev_t = t
        return []

Optimization: filter out invalid time diff for each slot solution 2

class Solution:
    def minAvailableDuration(self, slots1: List[List[int]], slots2: List[List[int]], duration: int) -> List[int]:
        """ tc O((M+N)log(M+N))  sc O(N+M)
        """
        # filter out  time slots not meeting the min diff >= duration 
        timeslots = list(filter(lambda x: x[1] - x[0] >= duration, slots1 + slots2))
        #print(timeslots)
        heapq.heapify(timeslots)

        while len(timeslots) > 1:
            start1, end1 = heapq.heappop(timeslots) # t1 must <= t2
            start2, end2 = timeslots[0]
            if end1 >= start2 + duration:
                return [start2, start2 + duration]
        return []

More optimization !!!!!! two pointer


class Solution:
    def minAvailableDuration(self, A: List[List[int]], B: List[List[int]], duration: int) -> List[int]:
        """
        tc O(NlgN+MlgM)  sc O(1)
        """
        A.sort()
        B.sort()
        n1,n2,p1,p2 = len(A),len(B),0,0
        while p2 < n2 and p1 < n1:
            # get overlap invertal  point 
            start = max(A[p1][0],B[p2][0])
            end = min(A[p1][1],B[p2][1])
            if end - start >= duration : # filter out non-overlap cases 
                # find answer 
                return [start,start+duration]
            # move p1 or p2 by comparing end time 
            elif A[p1][1] < B[p2][1]:
                p1 += 1
            elif A[p1][1] >= B[p2][1]:
                p2 += 1
        return []