Open In App

Find Next Optimal Range in Array

Last Updated : 06 Dec, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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:

C++




#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;
}


Java




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 + " ");
        }
    }
}


Python3




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=" ")


C#




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 + " ");
        }
    }
}


Javascript




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(" "));


Output

1 -1 -1 2 







Time Complexity: O(N*log N)
Auxiliary Space: O(N)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads