Maximizing Business Profit with Non-Overlapping Ranges
Last Updated :
06 Nov, 2023
Given an integer N representing the total number of products and queries[][] of size M. For each index i, queries[i] = [start, end, profit] which represents the profit the businessman will get by selling the products within the range [start, end], the task is to maximize the profit of the businessman such that each product can be sold at max once, that is there should be no overlapping of ranges.
Examples:
Input: N = 5, M = 4, queries[][] = { {1, 4, 5}, {0, 2, 3}, {3, 4, 5}, {0, 3, 6}}
Output: 8
Explanation: There are 5 products. To maximize the profit, it is better to go with {0, 2, 3} and {3, 4, 5}. Therefore, the maximum profit will be 3 + 5 = 8
Input: N= 7, M = 4, queries[][] = { {1, 3, 50}, {2, 4, 10}, {3, 5, 40}, {4, 6, 70} }
Output: 120
Explanation: There are total 7 products. To maximize the profit, it is better to go with {1, 3, 50} and {4, 6, 70}. Therefore, the maximum profit will be 50 + 70 = 120
Approach: This can be solved with the following approach:
Sort the queries in increasing order of the starting point of ranges and maintain a dp[] array such that dp[i] = maximum profit which can be achieved using queries[i…M]. We can use binary search to get the next starting product which the businessman can sell.
Steps to solve the problem:
- Create a dp[] array to store the answers calculated and prevent unnecessary recursive calls.
- Create a function maximumProfit(idx, queries[][], dp), to get the maximum profit which can be achieved using queries[idx…M]. Inside the function,
- Check if index has reached the end of queries, then simply return 0.
- Check the dp[] array to see if we have previously calculated the answer for index idx, if yes then simply return dp[idx]
- At any index idx, the businessman has 2 choices,
- Do not take the current query present at index idx into our final answer.
- Take the query present at idx, that is sell the products in the range [queries[idx][0], queries[idx][1]] to get the profit queries[idx][2] and then again start selling the products after queries[idx][1]. We can find the next product which the businessman can sell using binary search to decrease our search time.
- Return the maximum of the above 2 choices.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int maximumProfit( int idx, vector<vector< int > >& queries,
vector< int >& dp)
{
if (idx == queries.size())
return 0;
if (dp[idx] != -1)
return dp[idx];
int notTake = maximumProfit(idx + 1, queries, dp);
int low = idx + 1, high = queries.size() - 1;
int next_idx = queries.size();
while (low <= high) {
int mid = (low + high) / 2;
if (queries[mid][0] > queries[idx][1]) {
high = mid - 1;
next_idx = mid;
}
else {
low = mid + 1;
}
}
int take = queries[idx][2]
+ maximumProfit(next_idx, queries, dp);
return dp[idx] = max(take, notTake);
}
int maximizeTheProfit( int n, vector<vector< int > >& queries)
{
int m = queries.size();
sort(queries.begin(), queries.end());
vector< int > dp(m, -1);
return maximumProfit(0, queries, dp);
}
int main()
{
int N = 5;
vector<vector< int > > queries = {
{ 1, 4, 5 }, { 0, 2, 3 }, { 3, 4, 5 }, { 0, 3, 6 }
};
cout << maximizeTheProfit(N, queries) << endl;
return 0;
}
|
Java
import java.util.*;
public class Main {
static int maximumProfit( int idx, List< int []> queries, int [] dp) {
if (idx == queries.size())
return 0 ;
if (dp[idx] != - 1 )
return dp[idx];
int notTake = maximumProfit(idx + 1 , queries, dp);
int low = idx + 1 , high = queries.size() - 1 ;
int next_idx = queries.size();
while (low <= high) {
int mid = (low + high) / 2 ;
if (queries.get(mid)[ 0 ] > queries.get(idx)[ 1 ]) {
high = mid - 1 ;
next_idx = mid;
} else {
low = mid + 1 ;
}
}
int take = queries.get(idx)[ 2 ] + maximumProfit(next_idx, queries, dp);
return dp[idx] = Math.max(take, notTake);
}
static int maximizeTheProfit( int n, List< int []> queries) {
int m = queries.size();
queries.sort((a, b) -> Integer.compare(a[ 0 ], b[ 0 ]));
int [] dp = new int [m];
Arrays.fill(dp, - 1 );
return maximumProfit( 0 , queries, dp);
}
public static void main(String[] args) {
int N = 5 ;
List< int []> queries = new ArrayList<>();
queries.add( new int [] { 1 , 4 , 5 });
queries.add( new int [] { 0 , 2 , 3 });
queries.add( new int [] { 3 , 4 , 5 });
queries.add( new int [] { 0 , 3 , 6 });
System.out.println(maximizeTheProfit(N, queries));
}
}
|
Python3
def maximumProfit(idx, queries, dp):
if idx = = len (queries):
return 0
if dp[idx] ! = - 1 :
return dp[idx]
notTake = maximumProfit(idx + 1 , queries, dp)
low, high = idx + 1 , len (queries) - 1
next_idx = len (queries)
while low < = high:
mid = (low + high) / / 2
if queries[mid][ 0 ] > queries[idx][ 1 ]:
high = mid - 1
next_idx = mid
else :
low = mid + 1
take = queries[idx][ 2 ] + maximumProfit(next_idx, queries, dp)
dp[idx] = max (take, notTake)
return dp[idx]
def maximizeTheProfit(n, queries):
m = len (queries)
queries.sort()
dp = [ - 1 ] * m
return maximumProfit( 0 , queries, dp)
N = 5
queries = [
[ 1 , 4 , 5 ], [ 0 , 2 , 3 ], [ 3 , 4 , 5 ], [ 0 , 3 , 6 ]
]
print (maximizeTheProfit(N, queries))
|
C#
using System;
using System.Collections.Generic;
class GFG
{
static int MaximumProfit( int idx, List< int []> queries, int [] dp)
{
if (idx == queries.Count)
return 0;
if (dp[idx] != -1)
return dp[idx];
int notTake = MaximumProfit(idx + 1, queries, dp);
int low = idx + 1, high = queries.Count - 1;
int nextIdx = queries.Count;
while (low <= high)
{
int mid = (low + high) / 2;
if (queries[mid][0] > queries[idx][1])
{
high = mid - 1;
nextIdx = mid;
}
else
{
low = mid + 1;
}
}
int take = queries[idx][2] + MaximumProfit(nextIdx, queries, dp);
return dp[idx] = Math.Max(take, notTake);
}
static int MaximizeTheProfit( int n, List< int []> queries)
{
int m = queries.Count;
queries.Sort((a, b) => a[0].CompareTo(b[0]));
int [] dp = new int [m];
for ( int i = 0; i < m; i++)
{
dp[i] = -1;
}
return MaximumProfit(0, queries, dp);
}
public static void Main( string [] args)
{
int N = 5;
List< int []> queries = new List< int []>
{
new int [] {1, 4, 5},
new int [] {0, 2, 3},
new int [] {3, 4, 5},
new int [] {0, 3, 6}
};
Console.WriteLine(MaximizeTheProfit(N, queries));
}
}
|
Javascript
function maximumProfit(idx, queries, dp) {
if (idx === queries.length)
return 0;
if (dp[idx] !== -1)
return dp[idx];
let notTake = maximumProfit(idx + 1, queries, dp);
let low = idx + 1;
let high = queries.length - 1;
let nextIdx = queries.length;
while (low <= high) {
let mid = Math.floor((low + high) / 2);
if (queries[mid][0] > queries[idx][1]) {
high = mid - 1;
nextIdx = mid;
} else {
low = mid + 1;
}
}
let take = queries[idx][2] + maximumProfit(nextIdx, queries, dp);
dp[idx] = Math.max(take, notTake);
return dp[idx];
}
function maximizeTheProfit(n, queries) {
queries.sort((a, b) => a[0] - b[0]);
let m = queries.length;
let dp = new Array(m).fill(-1);
return maximumProfit(0, queries, dp);
}
let N = 5;
let queries = [
[1, 4, 5],
[0, 2, 3],
[3, 4, 5],
[0, 3, 6]
];
console.log(maximizeTheProfit(N, queries));
|
Time Complexity: O(M log M), where M is the size of queries[][] array.
Auxiliary Space: O(M)
Share your thoughts in the comments
Please Login to comment...