Given an array ranges[][] of size N x 2, where for every i, range[i][0] is the start and range[i][1] is the end of the range. For every range, find the index of the Next Optimal Range. For a range i which ends at a point X, all the ranges that have their starting points >= X will be the Next Optimal Range. In the case of multiple Next Optimal Range, the range with the smallest starting point is the most optimal. If there is no optimal range of any index i, then the answer for i-th index will be -1.
Note: The ranges have unique starting points.
Examples:
Input: ranges = [[-1, -1], [-2, 3], [3, 3]]
Output: [0,2,2]
Explanation: For i = 0, start = -1 and end = -1, so the only range which starts at or after -1, is the range [3, 3] which is at index 0.For i = 1, start = -2 and end = 3, so the only range which starts at or after 3, is the range [3, 3], which is at index. For i = 2, start = 3 and end = 3, so the only range which starts at or after 3, is the range [3, 3], which is at index 2.Input: ranges = [[-1, -1], [2, 3], [-3, 3], [-50, -20]]
Output: [1, -1, -1, 2]
Explanation: For i = 0, start = -1 and end = -1, so the only range which starts after at or after -1, is the range [2, 3] which is at index 1.For i = 1, start = 2 and end = 3, so no range starts at or after 3, therefore -1. For i = 2, start = -3 and end = 3, so no range starts at or after 3, therefore -1. For i = 3, start = -50 and end = -20, so the ranges which start at or after -20 are range [-3,3], [-1,1] and [2,3] so the we will consider range with smallest starting point, therefore the answer is the range [-3,3] which is at index 2.
Approach: To solve the problem follow the below idea:
This problem can be solved using Binary Search. Firstly, we can declare a map, say indexes which stores the index of every starting point. Now for every range i we can use using binary search to find the index of the range which has least starting point after the ending of i. If there is no range then the answer will be -1
Follow the steps mentioned below to implement the idea:
- Declare an array result[] to store the final answer.
- Declare a map indexes to store the index of every starting point.
- Iterate over all the ranges and find the lowerbound for ending of ith range in indexes.
- If we find a range, then store its index at result[i]
- Else store -1 at result[i]
- Return result
Below is the implementation of the above approach:
#include <bits/stdc++.h> using namespace std;
// Function to find Next Optimal Ranges vector< int >
findNextOptimalRange(vector<vector< int > >& ranges)
{ map< int , int > indexes;
vector< int > result;
// Store the index of all starting points
for ( int i = 0; i < ranges.size(); i++) {
int start = ranges[i][0];
indexes[start] = i;
}
// Find the Next Optimal Range for every index
for (vector< int > range : ranges) {
auto nextOptimalRange
= indexes.lower_bound(range[1]);
if (nextOptimalRange != indexes.end()) {
int index = (*nextOptimalRange).second;
result.push_back(index);
}
else
result.push_back(-1);
}
return result;
} // Drivers code int main()
{ vector<vector< int > > ranges{
{ -1, 1 }, { 2, 3 }, { -3, 3 }, { -50, -20 }
};
vector<vector< int > > ranges1{ { -1, -1 },
{ -2, 3 },
{ 3, 3 } };
// Function call
vector< int > result = findNextOptimalRange(ranges1);
for ( int i : result) {
cout << i << " ";
}
return 0;
} |
import java.util.*;
public class GFG {
// Function to find Next Optimal Ranges
public static List<Integer> findNextOptimalRange(
List<Map.Entry<Integer, Integer> > ranges)
{
Map<Integer, Integer> indexes = new TreeMap<>();
List<Integer> result = new ArrayList<>();
// Store the index of all starting points
for ( int i = 0 ; i < ranges.size(); i++) {
int start = ranges.get(i).getKey();
indexes.put(start, i);
}
// Find the next optimal range for every index
for (Map.Entry<Integer, Integer> range1 : ranges) {
Integer nextOptimalRange = null ;
for ( int key : indexes.keySet()) {
if (key > range1.getValue()) {
nextOptimalRange = indexes.get(key);
break ;
}
}
if (nextOptimalRange != null ) {
result.add(nextOptimalRange);
}
else {
result.add(- 1 );
}
}
return result;
}
// Main method
public static void main(String[] args)
{
List<Map.Entry<Integer, Integer> > ranges
= new ArrayList<>();
ranges.add(Map.entry(- 1 , 1 ));
ranges.add(Map.entry( 2 , 3 ));
ranges.add(Map.entry(- 3 , 3 ));
ranges.add(Map.entry(- 50 , - 20 ));
// Function call
List<Integer> result = findNextOptimalRange(ranges);
for ( int i : result) {
System.out.print(i + " " );
}
}
} |
def find_next_optimal_range(ranges):
indexes = {}
result = []
# Store the index of all starting points
for i in range ( len (ranges)):
start = ranges[i][ 0 ]
indexes[start] = i
# Find the next optimal range for every index
for range1 in ranges:
next_optimal_range = None
for key in sorted (indexes.keys()):
if key > range1[ 1 ]:
next_optimal_range = indexes[key]
break
if next_optimal_range is not None :
result.append(next_optimal_range)
else :
result.append( - 1 )
return result
# Driver code ranges = [( - 1 , 1 ), ( 2 , 3 ), ( - 3 , 3 ), ( - 50 , - 20 )]
ranges1 = [( - 1 , - 1 ), ( - 2 , 3 ), ( 3 , 3 )]
# Function call result = find_next_optimal_range(ranges)
for i in result:
print (i, end = " " )
|
using System;
using System.Collections.Generic;
using System.Linq;
public class GFG
{ // Function to find Next Optimal Ranges
public static List< int > FindNextOptimalRange(List<Tuple< int , int >> ranges)
{
Dictionary< int , int > indexes = new Dictionary< int , int >();
List< int > result = new List< int >();
// Store the index of all starting points
for ( int i = 0; i < ranges.Count; i++)
{
int start = ranges[i].Item1;
indexes[start] = i;
}
// Find the next optimal range for every index
foreach ( var range1 in ranges)
{
int ? nextOptimalRange = null ;
foreach ( int key in indexes.Keys.OrderBy(k => k))
{
if (key > range1.Item2)
{
nextOptimalRange = indexes[key];
break ;
}
}
if (nextOptimalRange != null )
{
result.Add(nextOptimalRange.Value);
}
else
{
result.Add(-1);
}
}
return result;
}
// Main method
public static void Main( string [] args)
{
List<Tuple< int , int >> ranges = new List<Tuple< int , int >> {
Tuple.Create(-1, 1),
Tuple.Create(2, 3),
Tuple.Create(-3, 3),
Tuple.Create(-50, -20)
};
// List<Tuple<int, int>> ranges1 = new List<Tuple<int, int>> {
// Tuple.Create(-1, -1),
// Tuple.Create(-2, 3),
// Tuple.Create(3, 3)
// };
// Function call
List< int > result = FindNextOptimalRange(ranges);
foreach ( int i in result)
{
Console.Write(i + " " );
}
}
} |
function GFG(ranges) {
const indexes = {};
const result = [];
// Store the index of the all starting points
for (let i = 0; i < ranges.length; i++) {
const start = ranges[i][0];
indexes[start] = i;
}
// Find the next optimal range for the every index
for (const range1 of ranges) {
let nextOptimalRange = null ;
for (const key of Object.keys(indexes).sort((a, b) => a - b)) {
if (key > range1[1]) {
nextOptimalRange = indexes[key];
break ;
}
}
if (nextOptimalRange !== null ) {
result.push(nextOptimalRange);
} else {
result.push(-1);
}
}
return result;
} // Driver code const ranges = [[-1, 1], [2, 3], [-3, 3], [-50, -20]]; const ranges1 = [[-1, -1], [-2, 3], [3, 3]]; // Function call const result = GFG(ranges); console.log(result.join( " " ));
|
1 -1 -1 2
Time Complexity: O(N*log N)
Auxiliary Space: O(N)