Skip to content
Related Articles
Open in App
Not now

Related Articles

Minimum number of integers required such that each Segment contains at least one of them

Improve Article
Save Article
  • Difficulty Level : Easy
  • Last Updated : 25 Jan, 2023
Improve Article
Save Article

Given two arrays start[] and end[] consisting of positive integers denoting the starting and ending points of a segment respectively, the task is to find the minimum number of integers which lies in at least one of the given segments and each segment contains at least one of them.

Examples: 

Input: start[] = {1, 2, 3}, end[] = { 3, 5, 6} 
Output:
Explanation: 
All three ranges ([1, 3], [2, 5], [3, 6]) contains the integer 3. 

Input: start[] = {4, 1, 2, 5}, end[] = {7, 3, 5, 6} 
Output: 3 6 
Explanation: 
Segments {1, 3} and {2, 5} are contains the integer 3. 
Segments {4, 7} and {5, 6} contains the integer 6. 

Mathematical formulation: 
The mathematical way of describing the problem is to consider each given range of integers to be a line segment defined by two integer coordinates [ai, bi] on a line. Then the minimum number of integers required to cover each of the given range is the minimum number of points such that each segment contains at least one point. 
The representation of Example 1 is shown below: 

Naive approach: 

The simplest way to solve the problem is to find the least value of all the starting points and maximum value of all ending points of all segments. Iterate over this range, and for each point in this range keep track of the number of segments which can be covered using this point. Use an array to store the number of segments as:

arr[point] = number of segments that can be covered using this point

  1. Find the maximum value in the array arr[].
  2. If this maximum value is equal to N, the index corresponding to this value is the point which covers all segments.
  3. If this maximum value is less than N, then the index corresponding to this value is a point which covers some segments.
  4. Repeat the steps 1 to 3 for array arr[] excluding this maximum value until the sum of all the maximum values found is equal to N.

Time Complexity: O((A-B+1)*N), where A is maximum of ending points of segments and B is the minimum of the starting points of the segments. 
Auxiliary Space: O(1)

Efficient Approach:

Approach 1:

The problem can be solved efficiently by using the Greedy Technique. Follow the steps given below to solve the problem: 

  • Sort the segments by their end points.
  • Select the point(or coordinate) corresponding to minimum end point of all segments.
  • Now, All the segments whose starting point are less than this selected point and whose ending points are greater than this selected point can be covered by this point.
  • Then print the minimum number of points.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// function to sort the 2D vector
// on basis of second element.
bool sortcol(const pair<int, int> p1,
             const pair<int, int> p2)
{
    return p1.second < p2.second;
}
 
// Function to compute minimum number
// of points which cover all segments
void minPoints(pair<int, int> points[], int n)
{
     
    // Sort the list of tuples by
    // their second element.
    sort(points, points + n, sortcol);
 
    // To store the solution
    vector<int> coordinates;
    int i = 0;
 
    // Iterate over all the segments
    while (i < n)
    {
        int seg = points[i].second;
        coordinates.push_back(seg);
        int p = i + 1;
 
        if (p >= n)
            break;
 
        // Get the start point of next segment
        int arrived = points[p].first;
 
        // Loop over all those segments whose
        // start point is less than the end
        // point of current segment
        while (seg >= arrived)
        {
            p += 1;
 
            if (p >= n)
                break;
 
            arrived = points[p].first;
        }
        i = p;
    }
     
    // Print the possibles values of M
    for(auto point : coordinates)
        cout << point << " ";
}
 
// Driver code
int main()
{
    int n = 4;
 
    // Starting points of segments
    int start[] = { 4, 1, 2, 5 };
 
    // Ending points of segments
    int end[] = { 7, 3, 5, 6 };
 
    pair<int, int> points[n];
 
    // Insert ranges in points[]
    for(int i = 0; i < n; i++)
    {
        points[i] = { start[i], end[i] };
    }
 
    // Function call
    minPoints(points, n);
 
    return 0;
}
 
// This code is contributed by Kingash

Java




// Java program for the above approach
import java.util.*;
 
class GFG{
     
// Function to compute minimum number
// of points which cover all segments
static void minPoints(int[][] points, int n)
{
     
    // Sort the list of tuples by
    // their second element.
    Arrays.sort(points, (a, b) -> a[1] - b[1]);
 
    // To store the solution
    ArrayList<Integer> coordinates = new ArrayList<>();
    int i = 0;
 
    // Iterate over all the segments
    while (i < n)
    {
        int seg = points[i][1];
        coordinates.add(seg);
        int p = i + 1;
 
        if (p >= n)
            break;
 
        // Get the start point of next segment
        int arrived = points[p][0];
 
        // Loop over all those segments whose
        // start point is less than the end
        // point of current segment
        while (seg >= arrived)
        {
            p += 1;
             
            if (p >= n)
                break;
                 
            arrived = points[p][0];
        }
        i = p;
    }
 
    // Print the possibles values of M
    for(Integer point : coordinates)
        System.out.print(point + " ");
}
 
// Driver code
public static void main(String[] args)
{
 
    int n = 4;
 
    // Starting points of segments
    int[] start = { 4, 1, 2, 5 };
 
    // Ending points of segments
    int[] end = { 7, 3, 5, 6 };
 
    int[][] points = new int[n][2];
 
    // Insert ranges in points[]
    for(int i = 0; i < n; i++)
    {
        points[i][0] = start[i];
        points[i][1] = end[i];
    }
 
    // Function call
    minPoints(points, n);
}
}
 
// This code is contributed by offbeat

Python3




# Python3 program for the above approach
 
# Function to compute minimum number
# of points which cover all segments
def minPoints(points):
 
    # Sort the list of tuples by
    # their second element.
    points.sort(key = lambda x: x[1])
 
    # To store the solution
    coordinates = []
    i = 0
 
    # Iterate over all the segments
    while i < n:
 
        seg = points[i][1]
        coordinates.append(seg)
        p = i + 1
 
        if p >= n:
            break
 
        # Get the start point of next segment
        arrived = points[p][0]
 
        # Loop over all those segments whose
        # start point is less than the end
        # point of current segment
        while seg >= arrived:
 
            p += 1
            if p >= n:
                break
            arrived = points[p][0]
        i = p
 
# Print the possibles values of M
    for point in coordinates:
        print(point, end =" ")
 
 
# Driver Code
n = 4
 
# Starting points of segments
start = [4, 1, 2, 5]
 
# Ending points of segments
end = [7, 3, 5, 6]
 
points = []
 
# Insert ranges in points[]
for i in range(n):
    tu = (start[i], end[i])
    points.append(tu)
 
# Function Call
minPoints(points)

C#




// C# program for the above approach
using System;
using System.Linq;
using System.Collections.Generic;
 
 
class GFG{
 
  // Function to compute minimum number
  // of points which cover all segments
  static void minPoints(List<int []> points, int n)
  {
 
    // Sort the list of tuples by
    // their second element.
    points = points.OrderBy(p => p[1]).ToList();
 
 
    // To store the solution
    List<int> coordinates = new List<int>();
    int i = 0;
 
    // Iterate over all the segments
    while (i < n)
    {
      int seg = points[i][1];
      coordinates.Add(seg);
      int p = i + 1;
 
      if (p >= n)
        break;
 
      // Get the start point of next segment
      int arrived = points[p][0];
 
      // Loop over all those segments whose
      // start point is less than the end
      // point of current segment
      while (seg >= arrived)
      {
        p += 1;
 
        if (p >= n)
          break;
 
        arrived = points[p][0];
      }
      i = p;
    }
 
    // Print the possibles values of M
    foreach (int point in coordinates)
      Console.Write(point + " ");
  }
 
  // Driver code
  public static void Main(string[] args)
  {
 
    int n = 4;
 
    // Starting points of segments
    int[] start = { 4, 1, 2, 5 };
 
    // Ending points of segments
    int[] end = { 7, 3, 5, 6 };
 
    List<int []> points = new List<int []>();
 
    // Insert ranges in points[]
    for(int i = 0; i < n; i++)
    {
      points.Add( new [] {start[i], end[i]});
    }
 
    // Function call
    minPoints(points, n);
  }
}
 
// This code is contributed by phasing17

Javascript




<script>
 
// JavaScript program for the above approach
 
// Function to compute minimum number
// of points which cover all segments
function minPoints(points){
 
    // Sort the list of tuples by
    // their second element.
    points.sort((a,b)=>a[1]-b[1])
 
    // To store the solution
    let coordinates = []
    let i = 0
 
    // Iterate over all the segments
    while(i < n){
 
        let seg = points[i][1]
        coordinates.push(seg)
        let p = i + 1
 
        if(p >= n)
            break
 
        // Get the start point of next segment
        let arrived = points[p][0]
 
        // Loop over all those segments whose
        // start point is less than the end
        // point of current segment
        while(seg >= arrived){
 
            p += 1
            if(p >= n)
                break
            arrived = points[p][0]
        }
        i = p
    }
 
    // Print the possibles values of M
    for(let point of coordinates)
        document.write(point," ")
}
 
// Driver Code
let n = 4
 
// Starting points of segments
let start = [4, 1, 2, 5]
 
// Ending points of segments
let end = [7, 3, 5, 6]
 
let points = []
 
// Insert ranges in points[]
for(let i = 0; i < n; i++){
    let tu = [start[i], end[i]]
    points.push(tu)
}
 
// Function Call
minPoints(points)
 
// This code is contributed by shinjanpatra
 
</script>

Output

3 6 

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

Approach 2: Divide and Conquer Algorithm

Another approach to solve the problem of finding the minimum number of points needed to cover a set of intervals, which uses a divide and conquer algorithm.

  • The idea behind the divide and conquer algorithm is to recursively divide the intervals into two halves and find the minimum number of points needed to cover each half. 
  • Then, we can combine the solutions for the two halves by using a point to cover the intervals that overlap.

Follow the Below steps to solve the above approach:

  • If there is only one interval, return 1.
  • Divide the intervals into two halves.
  • Recursively find the minimum number of points needed to cover the left and right halves.
  • Initialize the minimum number of points to cover the overlapping intervals to the maximum of the two halves.
  • Iterate through the left and right halves.
  • If the intervals overlap, update the minimum number of points to cover the overlapping intervals.
  • Return the minimum number of points to cover the overlapping intervals.

Below is the implementation of the above approach:

C++




// CPP program to find the minimum number of points needed
// to cover all of the intervals using Divide Algorithm
#include <bits/stdc++.h>
using namespace std;
 
int minimumPoints(vector<pair<int, int> > intervals)
{
    sort(intervals.begin(), intervals.end(),
         [](pair<int, int> a, pair<int, int> b) {
             return a.second < b.second;
         });
    vector<int> points;
    points.push_back(intervals[0].second);
    for (int i = 1; i < intervals.size(); i++) {
        if (intervals[i].first > points.back()) {
            points.push_back(intervals[i].second);
        }
    }
    return points.size();
}
 
int main()
{
    // Define the intervals
    vector<pair<int, int> > intervals
        = { { 1, 3 }, { 2, 4 }, { 3, 5 }, { 6, 8 } };
    // Compute the minimum number of points needed to cover
    // the intervals and print it
    cout << minimumPoints(intervals) << endl; // Output: 2
 
    intervals = { { 1, 2 }, { 3, 4 }, { 2, 5 }, { 5, 8 } };
    cout << minimumPoints(intervals) << endl; // Output: 3
}
 
// This code is contributed by Susobhan Akhuli

Output

2
3

Complexity Analysis:

Time complexity: O(N*logN), due to the recursive nature of the algorithm, where N is the number of intervals.
Auxiliary Space: O(N), since we need to store the intervals in each recursive call.


My Personal Notes arrow_drop_up
Related Articles

Start Your Coding Journey Now!