You are given a 2D integer array intervals, where intervals[i] = [li, ri, weighti]. Interval i starts at position li and ends at ri, and has a weight of weighti. You can choose up to 4 non-overlapping intervals. The score of the chosen intervals is defined as the total sum of their weights.
Return the lexicographically smallest array of at most 4 indices from intervals with maximum score, representing your choice of non-overlapping intervals.
Two intervals are said to be non-overlapping if they do not share any points. In particular, intervals sharing a left or right boundary are considered overlapping.
Example 1:
Input: intervals = [[1,3,2],[4,5,2],[1,5,5],[6,9,3],[6,7,1],[8,9,1]]
Output: [2,3]
Explanation:
You can choose the intervals with indices 2, and 3 with respective weights of 5, and 3.
Example 2:
Input: intervals = [[5,8,1],[6,7,7],[4,7,3],[9,10,6],[7,8,2],[11,14,3],[3,5,5]]
Output: [1,3,5,6]
Explanation:
You can choose the intervals with indices 1, 3, 5, and 6 with respective weights of 7, 6, 3, and 5.
Constraints:
1 <= intevals.length <= 5 * 104intervals[i].length == 3intervals[i] = [li, ri, weighti]1 <= li <= ri <= 1091 <= weighti <= 109When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force approach to finding the maximum score involves checking every possible combination of intervals. We explore all possible subsets of intervals, checking for overlaps and calculating the score for each valid combination. Eventually we'll check every possible set of intervals.
Here's how the algorithm would work step-by-step:
def maximum_score_of_non_overlapping_intervals(intervals):
maximum_score = 0
number_of_intervals = len(intervals)
for i in range(1 << number_of_intervals):
current_intervals = []
current_score = 0
for j in range(number_of_intervals):
if (i >> j) & 1:
current_intervals.append(intervals[j])
# Check for overlaps. It's crucial to avoid intervals clashing
is_valid = True
for first_interval_index in range(len(current_intervals)):
for second_interval_index in range(first_interval_index + 1, len(current_intervals)):
start_one, end_one, score_one = current_intervals[first_interval_index]
start_two, end_two, score_two = current_intervals[second_interval_index]
if not (end_one <= start_two or end_two <= start_one):
is_valid = False
break
if not is_valid:
break
# Only calculate score if set of intervals are non-overlapping
if is_valid:
for interval_start, interval_end, interval_score in current_intervals:
current_score += interval_score
maximum_score = max(maximum_score, current_score)
return maximum_scoreThe best strategy for this problem focuses on making choices one step at a time. We'll process the intervals in a specific order and decide at each step whether to include the current interval in our solution, always aiming for the maximum possible score. This avoids having to explore all the different combinations of intervals.
Here's how the algorithm would work step-by-step:
def maximum_score_of_non_overlapping_intervals(intervals):
# Sort intervals by end time in ascending order.
intervals.sort(key=lambda interval: interval[1])
selected_intervals = []
total_score = 0
for interval_start, interval_end, interval_score in intervals:
# Check for overlap with already selected intervals.
overlap = False
for selected_start, selected_end, _ in selected_intervals:
if interval_start < selected_end and interval_end > selected_start:
overlap = True
break
if not overlap:
# Include the interval if no overlap.
selected_intervals.append((interval_start, interval_end, interval_score))
total_score += interval_score
return total_score| Case | How to Handle |
|---|---|
| Empty input list of intervals | Return 0 as there are no intervals to select a score from. |
| Intervals with identical start and end times (duration 0) | Treat these intervals as valid and potentially part of an optimal solution. |
| Intervals sorted by start time are extremely skewed, with one very large interval. | The dynamic programming approach considers all possibilities regardless of input skew. |
| Intervals with negative start or end times. | The algorithm should correctly handle negative values if the problem allows for them, or error if they are invalid input |
| Large number of intervals leading to potential stack overflow in recursive approaches | Prefer dynamic programming (iterative) over recursive solutions to avoid stack overflow issues. |
| Intervals with overlapping or touching endpoints. | Clearly define whether intervals that share endpoints are considered overlapping or not, and handle accordingly in the overlap check. |
| Integer overflow when calculating scores with large interval values | Use a data type that can accommodate the potential maximum score value, such as long. |
| All intervals have negative scores. | Return 0, as it's better to select no intervals than any that would decrease the overall score. |