from typing import List, Tuple def solve_greedy(intervals: List[Tuple[int, int]]) -> List[Tuple[int, int]]: """ Greedy algorithm: Sort by end time, pick non-overlapping. O(N log N) """ if not intervals: return [] # Sort by end time sorted_intervals = sorted(intervals, key=lambda x: x[1]) selected = [] last_end_time = -float('inf') for start, end in sorted_intervals: if start >= last_end_time: selected.append((start, end)) last_end_time = end return selected def solve_brute_force(intervals: List[Tuple[int, int]]) -> List[Tuple[int, int]]: """ Brute Force algorithm: Try all combinations. O(2^N) - Only for small inputs! """ n = len(intervals) max_count = 0 best_subset = [] # Helper to check if a subset of intervals is valid (non-overlapping) def is_valid(subset): sorted_subset = sorted(subset, key=lambda x: x[1]) last_end = -float('inf') for start, end in sorted_subset: if start < last_end: return False last_end = end return True # Iterate through all 2^N subsets (using bitmask) # Limit N to avoid hanging if n > 20: # Fallback or error for safety, though we handle this in router usually return solve_greedy(intervals) # Cheating slightly for safety if called directly with large N for i in range(1 << n): subset = [] for j in range(n): if (i >> j) & 1: subset.append(intervals[j]) if is_valid(subset): if len(subset) > max_count: max_count = len(subset) best_subset = subset return best_subset