Open In App

Maximum Profit By Choosing A Subset Of Intervals (Using Priority-Queue)

Last Updated : 17 Feb, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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


Output

8

Time complexity: O(n Log n)
Auxiliary Space: O(n)

Related Articles:



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads