Maximum Profit By Choosing A Subset Of Intervals (Using Priority-Queue)
Last Updated :
17 Feb, 2023
Given a list intervals of n intervals, the ith element [s, e, p] denotes the starting point s, ending point e, and the profit p earned by choosing the ith interval. Find the maximum profit one can achieve by choosing a subset of non-overlapping intervals.
Two intervals [s1, e1, p1] and [s2, e2, p2] are said to be non-overlapping if [e1 ? s2] and [s1 < s2].
Examples:
Input: n = 3, intervals = {{1, 2, 4}, {1, 5, 7}, {2, 4, 4}}
Output: 8
Explanation: One can choose intervals [1, 2, 4] and [2, 4, 4] for a profit of 8.
Input: n = 3, intervals = {{1, 4, 4}, {2, 3, 7}, {2, 3, 4}}
Output: 7
Explanation: One can choose interval [2, 3, 7] for a profit of 7.
Approach: The above problem can be solved with the below idea:
To find the maximum profit, sorting according to start time will lead to the maximum number of interval selections.
Follow the below steps to solve the problem:
- sort the intervals based on their start time.
- Declare a min heap priority queue.
- Iterate over the intervals and push it into the priority queue in a pair {end time, profit}.
- For every ith interval, we pop out the element from our min heap and we would consider the maximum profit if its end time is lesser or equal to the start time of the ith interval.
Below is the implementation of the above approach:
C++
// C++ implementation of the above approach
#include <bits/stdc++.h>
using namespace std;
// The main function that returns the maximum
// possible profit from given array of
// intervals
int maximum_profit(int n, vector<vector<int> >& intervals)
{
// A utility vector to include startTime,
// endTime and profit in pair
vector<pair<int, pair<int, int> > > events;
for (int i = 0; i < intervals.size(); i++) {
events.push_back(
{ intervals[i][0],
{ intervals[i][1], intervals[i][2] } });
}
// Min heap to store endTime and profit
priority_queue<pair<int, int>, vector<pair<int, int> >,
greater<pair<int, int> > >
pq;
// Sort the event vector based on its start
// time
sort(events.begin(), events.end());
// Declare a variable to store max_profit
int max_profit = 0;
for (auto& e : events) {
// While pq is not empty and its a
// non-overlapping interval we pop it
// out from the min heap and we
// check for the maximum profit
while (!pq.empty() && pq.top().first <= e.first) {
max_profit = max(max_profit, pq.top().second);
pq.pop();
}
// Insert into min heap endTime and
// the profit
pq.push({ e.second.first,
max_profit + e.second.second });
}
// Check again if min heap is contain
// any elements
while (!pq.empty()) {
// Update max_profit
max_profit = max(max_profit, pq.top().second);
pq.pop();
}
// Maximum profit
return max_profit;
}
// Driver code
int main()
{
int n = 3;
vector<vector<int> > intervals
= { { 1, 2, 4 }, { 1, 5, 7 }, { 2, 4, 4 } };
// Function call
cout << maximum_profit(n, intervals);
return 0;
}
Java
import java.util.*;
class Main {
public static int maximumProfit(int n,
int[][] intervals)
{
// A utility list to include startTime, endTime and
// profit in pair
List<Map.Entry<
Integer, Map.Entry<Integer, Integer> > > events
= new ArrayList<>();
for (int i = 0; i < intervals.length; i++) {
events.add(new AbstractMap.SimpleEntry<>(
intervals[i][0],
new AbstractMap.SimpleEntry<>(
intervals[i][1], intervals[i][2])));
}
// Min heap to store endTime and profit
PriorityQueue<Map.Entry<Integer, Integer> > pq
= new PriorityQueue<>(
(a, b) -> a.getKey() - b.getKey());
// Sort the event list based on its start time
events.sort((a, b) -> a.getKey() - b.getKey());
// Declare a variable to store max_profit
int maxProfit = 0;
for (Map.Entry<Integer,
Map.Entry<Integer, Integer> > e :
events) {
// While pq is not empty and its a
// non-overlapping interval we pop it out from
// the min heap and we check for the maximum
// profit
while (!pq.isEmpty()
&& pq.peek().getKey() <= e.getKey()) {
maxProfit = Math.max(maxProfit,
pq.poll().getValue());
}
// Insert into min heap endTime and the profit
pq.offer(new AbstractMap.SimpleEntry<>(
e.getValue().getKey(),
maxProfit + e.getValue().getValue()));
}
// Check again if min heap is contain any elements
while (!pq.isEmpty()) {
// Update max_profit
maxProfit
= Math.max(maxProfit, pq.poll().getValue());
}
// Maximum profit
return maxProfit;
}
public static void main(String[] args)
{
int n = 3;
int[][] intervals
= { { 1, 2, 4 }, { 1, 5, 7 }, { 2, 4, 4 } };
// Function call
System.out.println(maximumProfit(n, intervals));
}
}
Python3
#Python code for the above approach
import heapq
# The main function that returns the maximum
# possible profit from given array of
# intervals
def maximum_profit(n, intervals):
# A utility vector to include startTime,
# endTime and profit in pair
events = []
for i in range(len(intervals)):
events.append((intervals[i][0], (intervals[i][1], intervals[i][2])))
# Min heap to store endTime and profit
pq = []
# Sort the event vector based on its start
# time
events.sort()
# Declare a variable to store max_profit
max_profit = 0
for e in events:
# While pq is not empty and its a
# non-overlapping interval we pop it
# out from the min heap and we
# check for the maximum profit
while pq and pq[0][0] <= e[0]:
max_profit = max(max_profit, pq[0][1])
heapq.heappop(pq)
# Insert into min heap endTime and
# the profit
heapq.heappush(pq, (e[1][0], max_profit + e[1][1]))
# Check again if min heap is contain
# any elements
while pq:
# Update max_profit
max_profit = max(max_profit, pq[0][1])
heapq.heappop(pq)
# Maximum profit
return max_profit
# Driver code
if __name__ == '__main__':
n = 3
intervals = [[1, 2, 4], [1, 5, 7], [2, 4, 4]]
# Function call
print(maximum_profit(n, intervals))
#This code is contributed by Potta Lokesh
C#
// C# implementation of the above approach
using System;
using System.Collections.Generic;
class Program
{
// The main function that returns the maximum
// possible profit from given array of
// intervals
static int MaximumProfit(int n, int[][] intervals)
{
// A utility list to include startTime,
// endTime and profit in pair
List<(int start, int end, int profit)> events = new List<(int start, int end, int profit)>();
for (int i = 0; i < intervals.Length; i++)
{
events.Add((intervals[i][0], intervals[i][1], intervals[i][2]));
}
// Sort the event list based on its start time
events.Sort((a, b) => a.start - b.start);
// Declare a variable to store max_profit
int maxProfit = 0;
// Min heap to store endTime and profit
List<(int end, int profit)> pq = new List<(int end, int profit)>();
foreach (var e in events)
{
// While pq is not empty and its a
// non-overlapping interval we pop it
// out from the min heap and we
// check for the maximum profit
while (pq.Count > 0 && pq[0].end <= e.start)
{
maxProfit = Math.Max(maxProfit, pq[0].profit);
pq.RemoveAt(0);
}
// Insert into min heap endTime and
// the profit
pq.Add((end: e.end, profit: maxProfit + e.profit));
}
// Check again if min heap is contain
// any elements
while (pq.Count > 0)
{
// Update max_profit
maxProfit = Math.Max(maxProfit, pq[0].profit);
pq.RemoveAt(0);
}
// Maximum profit
return maxProfit;
}
// Driver code
static void Main(string[] args)
{
int n = 3;
int[][] intervals = new int[][]
{
new int[] { 1, 2, 4 },
new int[] { 1, 5, 7 },
new int[] { 2, 4, 4 }
};
// Function call
Console.WriteLine(MaximumProfit(n, intervals));
}
}
// This code is contributed by rutikbhosale
JavaScript
// JavaScript implementation of the above approach
// The main function that returns the maximum
// possible profit from given array of
// intervals
function maximumProfit(n, intervals) {
// A utility array to include startTime,
// endTime and profit in pair
let events = []
for (let i = 0; i < intervals.length; i++) {
events.push({
start: intervals[i][0],
end: intervals[i][1],
profit: intervals[i][2]
});
}
// Sort the event array based on its start time
events.sort((a, b) => a.start - b.start);
// Declare a variable to store max_profit
let maxProfit = 0;
// Min heap to store endTime and profit
let pq = []
for (let e of events) {
// While pq is not empty and its a
// non-overlapping interval we pop it
// out from the min heap and we
// check for the maximum profit
while (pq.length > 0 && pq[0].end <= e.start) {
maxProfit = Math.max(maxProfit, pq[0].profit);
pq.shift();
}
// Insert into min heap endTime and
// the profit
pq.push({ end: e.end, profit: maxProfit + e.profit });
}
// Check again if min heap is contain
// any elements
while (pq.length > 0) {
// Update max_profit
maxProfit = Math.max(maxProfit, pq[0].profit);
pq.shift();
}
// Maximum profit
return maxProfit;
}
// Driver code
let n = 3;
let intervals = [
[1, 2, 4],
[1, 5, 7],
[2, 4, 4]
];
// Function call
console.log(maximumProfit(n, intervals));
//code by ksam24000
Time complexity: O(n Log n)
Auxiliary Space: O(n)
Related Articles:
Similar Reads
Maximum points covered after removing an Interval Given N intervals in the form [l, r] and an integer Q. The task is to find the interval which when removed results in the coverage of the maximum number of points (Union of all the rest of the intervals). Note that all the given intervals cover numbers between 1 to Q only. Examples: Input: intervals
9 min read
Find the point where maximum intervals overlap Consider a big party where a log register for guest's entry and exit times is maintained. Find the time at which there are maximum guests in the party. Given the Entry(Entry[]) and Exit (Exit[]) times of individuals at a place.Note: Entries in the register are not in sorted order.Examples: Input: En
14 min read
Coding Problems on Interval and Range Manipulation Interval and Range Manipulation problems are common in algorithmic challenges, often requiring efficient handling of ranges or intervals to solve a specific problem. These problems deal with tasks like merging intervals, finding overlaps, or calculating sums and differences of intervals. The main ch
2 min read
Turn a Queue into a Priority Queue What is Queue?Queue is an abstract data type that is open at both ends. One end is always used to insert data (enqueue) which is basically the rear/back/tail end and the other which is the front end is used to remove data (dequeue). Queue follows First-In-First-Out (FIFO) methodology, i.e., "the dat
9 min read
Minimum Set size for covering intervals Given an array arr[] consisting of N ranges of the form [L, R], the task is to determine the size of the smallest set that contains at least 2 integers within each interval. Examples: Input: arr[] = { {1, 3}, {2, 5}, {1, 4} }Output: 2Explanation: Interval [1, 3] contains the numbers 1, 2, 3.Interval
7 min read
What is Priority Queue | Introduction to Priority Queue A priority queue is a type of queue that arranges elements based on their priority values. Each element has a priority associated. When we add an item, it is inserted in a position based on its priority.Elements with higher priority are typically retrieved or removed before elements with lower prior
6 min read