Monday, November 25, 2024
Google search engine
HomeData Modelling & AIDivide N segments into two non-empty groups such that given condition is...

Divide N segments into two non-empty groups such that given condition is satisfied

Given N segments (or ranges) represented by two non-negative integers L and R. Divide these segments into two non-empty groups such that there are no two segments from different groups that share a common point. If it is possible to do so, assign each segment a number from the set {1, 2} otherwise print Not Possible.

Examples: 

Input: arr[][] = {{5, 5}, {2, 3}, {3, 4}} 
Output: 2 1 1 
Since 2nd and 3rd segment have one point common i.e. 3, they should be contained in same group.

Input: arr[][] = {{3, 5}, {2, 3}, {1, 4}} 
Output: Not Possible 
All segments should be contained in the same group since every pair has a common point with each other. Since the other group is empty, answer is not possible. 

Prerequisites: Merge Overlapping Intervals

Approach: 

Using the concept of merging overlapping intervals, we can assign the same group to all those segments that are overlapping and alternatively changing the group number. 
To merge overlapping segments, sort all the segments with respect to their increasing left values, if left values are equal, sort it on the basis of right values first keeping order of the original indices of the segments. Then, iterate over the segments and check if any of the previous segments is overlapping with the current segment. If it does then merge it making it one segment and if it doesn’t create a new one

At last, check if one of the group is empty of not. If one of them is empty, answer is not possible, otherwise print all the assigned values of segments.

Algorithm:

  1. Create a vector of pairs to store the segments with their left and right values and their original position.
  2. Sort the vector of pairs by their left values.
  3. Initialize a resultant vector with all values as 2, except for the first segment which is assigned a value of 1.
  4. Traverse the sorted vector of pairs starting from the second segment.
  5. Check if the left value of the current segment is less than or equal to the maximum right value encountered so far.
  6. If it is, then assign the same value as the previous segment to the resultant vector for the current segment and update the maximum right value encountered so far.
  7. If it is not, then we have found the breakpoint and can exit the loop.
  8. If the loop completes without finding the breakpoint, print the resultant vector.
  9. If the breakpoint is found, print “Not possible”.

Below is the implementation of the above approach:

C++




// C++ Program to divide N segments
// into two non empty groups such that
// given condition is satisfied
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to print the answer if
// it exists using the concept of
// merge overlapping segments
void printAnswer(vector<pair<int, int> > v, int n)
{
    // vec[i].first -> left value
    // vec[i].second.first -> right value
    // vec[i].second.second -> position
    vector<pair<int, pair<int, int> > > vec;
    for (int i = 0; i < n; i++) {
        vec.push_back({ v[i].first, { v[i].second, i } });
    }
    sort(vec.begin(), vec.end());
 
    // Resultant array
    //   Initialise all the values in resultant array with
    //   '2' except the position at the first index of
    //   sorted vec which is initialised as '1' Initialise
    //   maxR to store the maximum of all right values
    //   encountered so far
    vector<int> res(n, 2);
    int maxR = vec[0].second.first;
    res[vec[0].second.second] = 1;
 
    // If the i-th index has any point in common with the
    // (i-1)th index classify it as '1'
    //    in resultant array and update maxR if necessary
    // else we have found the breakpoint and we can exit the
    // loop
 
    bool ok = false;
    for (int i = 1; i < n; i++) {
        if (maxR >= vec[i].first) {
            res[vec[i].second.second]
                = res[vec[i - 1].second.second];
            maxR = max(maxR, vec[i].second.first);
        }
        else {
            ok = true;
            break;
        }
    }
    if (ok) {
        for (auto x : res)
            cout << x << " ";
        cout << '\n';
    }
    else
        cout << "Not possible\n";
}
 
int main()
{
    vector<pair<int, int> > v
        = { { 2, 8 }, { 3, 4 }, { 5, 8 }, { 9, 10 } };
    int n = (int)v.size();
 
    printAnswer(v, n);
}


Java




import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
 
public class Gfg {
    public static void main(String[] args)
    {
        List<Pair> v = Arrays.asList(
            new Pair(2, 8), new Pair(3, 4), new Pair(5, 8),
            new Pair(9, 10));
        int n = v.size();
        printAnswer(v, n);
    }
 
    static class Pair {
        int first;
        int second;
 
        public Pair(int first, int second)
        {
            this.first = first;
            this.second = second;
        }
    }
 
    static class Trio {
        int first;
        int second;
        int third;
 
        public Trio(int first, int second, int third)
        {
            this.first = first;
            this.second = second;
            this.third = third;
        }
    }
 
    static void printAnswer(List<Pair> v, int n)
    {
        List<Trio> vec = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            vec.add(new Trio(v.get(i).first,
                             v.get(i).second, i));
        }
        vec.sort(new Comparator<Trio>() {
            @Override public int compare(Trio o1, Trio o2)
            {
                return o1.first - o2.first;
            }
        });
 
        int[] res = new int[n];
        Arrays.fill(res, 2);
        int maxR = vec.get(0).second;
        res[vec.get(0).third] = 1;
 
        boolean ok = false;
        for (int i = 1; i < n; i++) {
            if (maxR >= vec.get(i).first) {
                res[vec.get(i).third]
                    = res[vec.get(i - 1).third];
                maxR = Math.max(maxR, vec.get(i).second);
            }
            else {
                ok = true;
                break;
            }
        }
        if (ok) {
            for (int x : res) {
                System.out.print(x + " ");
            }
            System.out.println();
        }
        else {
            System.out.println("Not possible");
        }
    }
}


Python3




# Python3 Program to divide N segments
# into two non empty groups such that
# given condition is satisfied
 
# Function to print the answer if
# it exists using the concept of
# merge overlapping segments
 
 
def printAnswer(v, n):
    # Sort the indices based on their corresponding value in V
    indices = list(range(n))
    indices.sort(key=lambda i: v[i])
 
    # Resultant array
    # Initialise all the values in resultant array with '2'
    # except the first index of 'indices' which is initialised as '1'
    # Initialise maxR to store the maximum of all right values encountered so far
    res = [2] * n
    res[indices[0]] = 1
    maxR = v[indices[0]][1]
 
    # If the i-th index has any point in common with the (i-1)th index classify it as '1' in resultant array and update maxR if necessary
    # else we have found the breakpoint and we can exit the loop
    for i in range(1, n):
        if maxR >= v[indices[i]][0]:
            res[indices[i]] = res[indices[i-1]]
            maxR = max(maxR, v[indices[i]][1])
        else:
            break
    else:
        print("Not possible")
        return
    print(" ".join(map(str, res)))
 
 
# Driver Code
if __name__ == "__main__":
 
    v = [[2, 8], [3, 4], [5, 8], [9, 10]]
    n = len(v)
    printAnswer(v, n)


C#




using System;
using System.Collections.Generic;
using System.Linq;
 
namespace DivideNSegments
{
    class Program
    {
        static void Main(string[] args)
        {
            List<(int, int)> v = new List<(int, int)>()
            {
                (2, 8), (3, 4), (5, 8), (9, 10)
            };
            int n = v.Count;
 
            PrintAnswer(v, n);
        }
 
        static void PrintAnswer(List<(int, int)> v, int n)
        {
            // vec[i].Item1 -> left value
            // vec[i].Item2.Item1 -> right value
            // vec[i].Item2.Item2 -> position
            List<(int, (int, int))> vec = new List<(int, (int, int))>();
            for (int i = 0; i < n; i++)
            {
                vec.Add((v[i].Item1, (v[i].Item2, i)));
            }
            vec = vec.OrderBy(x => x.Item1).ToList();
 
            // Resultant array
            // Initialise all the values in resultant array with '2' except the position at the first index of sorted vec which is initialised as '1'
            // Initialise maxR to store the maximum of all right values encountered so far
            List<int> res = Enumerable.Repeat(2, n).ToList();
            int maxR = vec[0].Item2.Item1;
            res[vec[0].Item2.Item2] = 1;
 
            // If the i-th index has any point in common with the (i-1)th index classify it as '1' in resultant array and update maxR if necessary
            // Else we have found the breakpoint and we can exit the loop
            bool ok = false;
            for (int i = 1; i < n; i++)
            {
                if (maxR >= vec[i].Item1)
                {
                    res[vec[i].Item2.Item2] = res[vec[i - 1].Item2.Item2];
                    maxR = Math.Max(maxR, vec[i].Item2.Item1);
                }
                else
                {
                    ok = true;
                    break;
                }
            }
            if (ok)
            {
                Console.WriteLine(String.Join(" ", res));
            }
            else
            {
                Console.WriteLine("Not possible");
            }
        }
    }
}
// This code has been contributed by Prince Kumar


Javascript




// JavaScript code to divide N segments into two non empty groups such that given condition is satisfied
 
// Function to print the answer if it exists using the concept of merge overlapping segments
function printAnswer(v, n) {
    // vec[i].first -> left value
    // vec[i].second.first -> right value
    // vec[i].second.second -> position
    var vec = [];
    for (var i = 0; i < n; i++) {
        vec.push([v[i][0], [v[i][1], i]]);
    }
    vec.sort(function(a,b){
        if(a[0] == b[0]){
            return a[1][0] - b[1][0];
        }
        return a[0] - b[0];
    });
 
    // Resultant array
    // Initialise all the values in resultant array with '2'
    // except the first index of 'vec' which is initialised as '1'
    // Initialise maxR to store the maximum of all right values encountered so far
    var res = Array(n).fill(2);
    var maxR = vec[0][1][0];
    res[vec[0][1][1]] = 1;
 
    // If the i-th index has any point in common with the (i-1)th index classify it as '1' in resultant array and update maxR if necessary
    // else we have found the breakpoint and we can exit the loop
    var ok = false;
    for (var i = 1; i < n; i++) {
        if (maxR >= vec[i][0]) {
            res[vec[i][1][1]] = res[vec[i - 1][1][1]];
            maxR = Math.max(maxR, vec[i][1][0]);
        } else {
            ok = true;
            break;
        }
    }
    if (ok) {
        console.log(res.join(" "));
    } else {
        console.log("Not possible");
    }
}
 
// Driver Code
var v = [[2, 8], [3, 4], [5, 8], [9, 10]];
var n = v.length;
printAnswer(v, n);
 
// This code is contributed by divya_p123.


Output

1 1 1 2 

Complexity Analysis:

  • Time Complexity: O(n * log n), where n is the number of segments
  • Auxiliary Space: O(n).  
Feeling lost in the world of random DSA topics, wasting time without progress? It’s time for a change! Join our DSA course, where we’ll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!

RELATED ARTICLES

Most Popular

Recent Comments