Given n appointments, find all conflicting appointments.
Examples:
Input: appointments[] = { {1, 5} {3, 7}, {2, 6}, {10, 15}, {5, 6}, {4, 100}}
Output: Following are conflicting intervals
[3,7] Conflicts with [1,5]
[2,6] Conflicts with [1,5]
[5,6] Conflicts with [3,7]
[4,100] Conflicts with [1,5]
An appointment is conflicting if it conflicts with any of the previous appointments in the array.
The Easy Way To Go Forward With: The Approach:
Kind of brute force we traverse over backside of current index and check for overlapping.
#include <bits/stdc++.h>
#include <iostream>
using namespace std;
int main()
{
// Given Appointments.
vector<vector<int> > v{
{ 1, 5 }, { 3, 7 }, { 2, 6 },
{ 10, 15 }, { 5, 6 }, { 4, 100 }
};
// sort according to start time of meet/appointment.
// sort(v.begin(), v.end());
// number of pair or appointments.
int n = v.size();
// for stoping the overlapping
// vector<bool>vis(n,0);
// traverse over and check for it.
vector<pair<pair<int, int>, pair<int, int> > > result;
for (int i = 0; i < n; i++) {
for (int j = i - 1; j >= 0; j--) {
// to reduce extra/unwanted comparisons.
// if(v[j][0]>v[i][1])break;
// else{
if (v[j][0] < v[i][1]) {
result.push_back({ { v[i][0], v[i][1] },
{ v[j][1], v[j][0] } });
}
// }
}
}
// final output.
for (auto it : result) {
cout << "[" << it.first.first << ","
<< it.first.second
<< "] having Conflict with [";
cout << it.second.first << "," << it.second.second
<< "]" << endl;
}
// code by Sanket Gode.
return 0;
}
import java.util.*;
public class Main {
static class Pair<K, V> {
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() {
return key;
}
public V getValue() {
return value;
}
}
public static void main(String[] args) {
// Given Appointments.
List<List<Integer>> v = new ArrayList<>();
v.add(Arrays.asList(1, 5));
v.add(Arrays.asList(3, 7));
v.add(Arrays.asList(2, 6));
v.add(Arrays.asList(10, 15));
v.add(Arrays.asList(5, 6));
v.add(Arrays.asList(4, 100));
// sort according to start time of meet/appointment.
// sort(v.begin(), v.end());
// number of pair or appointments.
int n = v.size();
// for stoping the overlapping
// vector<bool>vis(n,0);
// traverse over and check for it.
List<Pair<Pair<Integer, Integer>, Pair<Integer, Integer>>> result = new ArrayList<>();
for (int i = 0; i < n; i++) {
for (int j = i - 1; j >= 0; j--) {
// to reduce extra/unwanted comparisons.
// if(v[j][0]>v[i][1])break;
// else{
if (v.get(j).get(0) < v.get(i).get(1)) {
result.add(new Pair<>(
new Pair<>(v.get(i).get(0), v.get(i).get(1)),
new Pair<>(v.get(j).get(1), v.get(j).get(0))
));
}
}
}
// final output.
for (Pair<Pair<Integer, Integer>, Pair<Integer, Integer>> it : result) {
System.out.printf("[%d,%d] having Conflict with [%d,%d]\n",
it.getKey().getKey(), it.getKey().getValue(),
it.getValue().getKey(), it.getValue().getValue());
}
}
}
v = [[1, 5], [3, 7], [2, 6], [10, 15],
[5, 6], [4, 100]]
# sort according to start time of meet/appointment.
# v.sort()
# number of pair or appointments.
n = len(v)
# for stoping the overlapping
#vis = [0]*n
# traverse over and check for it.
result = []
for i in range(n):
for j in range(i-1, -1, -1):
# to reduce extra/unwanted comparisons.
# if(v[j][0]>v[i][1]):
# break
# else:
if v[j][0] < v[i][1]:
result.append([[v[i][0], v[i][1]], [v[j][1], v[j][0]]])
# final output.
for it in result:
print("[" + str(it[0][0]) + "," + str(it[0][1]) +
"] having Conflict with [" + str(it[1][0]) + "," + str(it[1][1]) + "]")
using System;
using System.Collections.Generic;
class Program {
static void Main(string[] args)
{
// Given Appointments.
List<List<int> > v = new List<List<int> >() {
new List<int>{ 1, 5 }, new List<int>{ 3, 7 },
new List<int>{ 2, 6 },
new List<int>{ 10, 15 },
new List<int>{ 5, 6 }, new List<int>
{
4, 100
}
};
// sort according to start time of meet/appointment.
// v.Sort();
// number of pair or appointments.
int n = v.Count;
// for stopping the overlapping
// List<bool> vis = new List<bool>(n);
// for (int i = 0; i < n; i++) vis.Add(false);
// traverse over and check for it.
List<Tuple<Tuple<int, int>, Tuple<int, int> > >
result = new List<Tuple<Tuple<int, int>,
Tuple<int, int> > >();
for (int i = 0; i < n; i++) {
for (int j = i - 1; j >= 0; j--) {
// to reduce extra/unwanted comparisons.
// if(v[j][0]>v[i][1])break;
// else{
if (v[j][0] < v[i][1]) {
result.Add(Tuple.Create(
Tuple.Create(v[i][0], v[i][1]),
Tuple.Create(v[j][1], v[j][0])));
}
// }
}
}
// final output.
foreach(var it in result)
{
Console.Write(
"[{0},{1}] having Conflict with [{2},{3}]\n",
it.Item1.Item1, it.Item1.Item2,
it.Item2.Item1, it.Item2.Item2);
}
}
}
// equivalent JavaScript code
const v = [[1, 5], [3, 7], [2, 6], [10, 15], [5, 6], [4, 100]];
// sort according to start time of meet/appointment.
// v.sort()
const n = v.length; // number of pair or appointments.
const result = [];
for (let i = 0; i < n; i++)
{
for (let j = i - 1; j >= 0; j--)
{
// to reduce extra/unwanted comparisons.
// if(v[j][0]>v[i][1]){
// break;
// }
// else{
if (v[j][0] < v[i][1]) {
result.push([
[v[i][0], v[i][1]],[v[j][1], v[j][0]]]);
}
}
}
// final output.
for (let it of result) {
console.log("[" + it[0][0] + "," + it[0][1] +
"] having Conflict with [" + it[1][0] + "," +
it[1][1] + "]");
}
Output
[3,7] having Conflict with [5,1] [2,6] having Conflict with [7,3] [2,6] having Conflict with [5,1] [10,15] having Conflict with [6,2] [10,15] having Conflict with [7,3] [10,15] having Conflict with [5,1] [5,6] having Conflict with [6,2] [5,6] having Conflict with [7,3] [5,6] having Conflict with [5,1] [4,100] having Conflict with [6,5] [4,100] having Conflict with [15,10] [4,100] having Conflict with [6,2] [4,100] having Conflict with [7,3] [4,100] having Conflict with [5,1]
Complexity Analysis:
Time Complexity: O(n^2).
Auxiliary Space: O(n)+O(n),in the worst case.
We strongly recommend to minimize the browser and try this yourself first.
A Simple Solution is to one by one process all appointments from the second appointment to last. For every appointment i, check if it conflicts with i-1, i-2, ... 0. The time complexity of this method is O(n2).
We can use Interval Tree to solve this problem in O(nLogn) time. Following is a detailed algorithm.
- Create an Interval Tree, initially with the first appointment.
- Do following for all other appointments starting from the second one.
- Check if the current appointment conflicts with any of the existing appointments in Interval Tree. If conflicts, then print the current appointment. This step can be done O(Logn) time.
- Insert the current appointment in Interval Tree. This step also can be done O(Logn) time.
Following is the implementation of the above idea.
// C++ program to print all conflicting appointments in a
// given set of appointments
#include <bits/stdc++.h>
using namespace std;
// Structure to represent an interval
struct Interval
{
int low, high;
};
// Structure to represent a node in Interval Search Tree
struct ITNode
{
Interval *i; // 'i' could also be a normal variable
int max;
ITNode *left, *right;
};
// A utility function to create a new Interval Search Tree Node
ITNode * newNode(Interval i)
{
ITNode *temp = new ITNode;
temp->i = new Interval(i);
temp->max = i.high;
temp->left = temp->right = NULL;
return temp;
};
// A utility function to insert a new Interval Search Tree
// Node. This is similar to BST Insert. Here the low value
// of interval is used tomaintain BST property
ITNode *insert(ITNode *root, Interval i)
{
// Base case: Tree is empty, new node becomes root
if (root == NULL)
return newNode(i);
// Get low value of interval at root
int l = root->i->low;
// If root's low value is smaller, then new interval
// goes to left subtree
if (i.low < l)
root->left = insert(root->left, i);
// Else, new node goes to right subtree.
else
root->right = insert(root->right, i);
// Update the max value of this ancestor if needed
if (root->max < i.high)
root->max = i.high;
return root;
}
// A utility function to check if given two intervals overlap
bool doOVerlap(Interval i1, Interval i2)
{
if (i1.low < i2.high && i2.low < i1.high)
return true;
return false;
}
// The main function that searches a given interval i
// in a given Interval Tree.
Interval *overlapSearch(ITNode *root, Interval i)
{
// Base Case, tree is empty
if (root == NULL) return NULL;
// If given interval overlaps with root
if (doOVerlap(*(root->i), i))
return root->i;
// If left child of root is present and max of left child
// is greater than or equal to given interval, then i may
// overlap with an interval is left subtree
if (root->left != NULL && root->left->max >= i.low)
return overlapSearch(root->left, i);
// Else interval can only overlap with right subtree
return overlapSearch(root->right, i);
}
// This function prints all conflicting appointments in a given
// array of appointments.
void printConflicting(Interval appt[], int n)
{
// Create an empty Interval Search Tree, add first
// appointment
ITNode *root = NULL;
root = insert(root, appt[0]);
// Process rest of the intervals
for (int i=1; i<n; i++)
{
// If current appointment conflicts with any of the
// existing intervals, print it
Interval *res = overlapSearch(root, appt[i]);
if (res != NULL)
cout << "[" << appt[i].low << "," << appt[i].high
<< "] Conflicts with [" << res->low << ","
<< res->high << "]\n";
// Insert this appointment
root = insert(root, appt[i]);
}
}
// Driver program to test above functions
int main()
{
// Let us create interval tree shown in above figure
Interval appt[] = { {1, 5}, {3, 7}, {2, 6}, {10, 15},
{5, 6}, {4, 100}};
int n = sizeof(appt)/sizeof(appt[0]);
cout << "Following are conflicting intervals\n";
printConflicting(appt, n);
return 0;
}
// Java program to print all conflicting
// appointments in a given set of appointments
class GfG{
// Structure to represent an interval
static class Interval
{
int low, high;
}
static class ITNode
{
// 'i' could also be a normal variable
Interval i;
int max;
ITNode left, right;
}
// A utility function to create a new node
static Interval newNode(int l, int h)
{
Interval temp = new Interval();
temp.low = l;
temp.high = h;
return temp;
}
// A utility function to create a new node
static ITNode newNode(Interval i)
{
ITNode temp = new ITNode();
temp.i = i;
temp.max = i.high;
temp.left = temp.right = null;
return temp;
}
// A utility function to insert a new
// Interval Search Tree Node. This is
// similar to BST Insert. Here the
// low value of interval is used to
// maintain BST property
static ITNode insert(ITNode root, Interval i)
{
// Base case: Tree is empty,
// new node becomes root
if (root == null)
return newNode(i);
// Get low value of interval at root
int l = root.i.low;
// If root's low value is smaller,
// then new interval goes to left subtree
if (i.low < l)
root.left = insert(root.left, i);
// Else, new node goes to right subtree.
else
root.right = insert(root.right, i);
// Update the max value of this
// ancestor if needed
if (root.max < i.high)
root.max = i.high;
return root;
}
// A utility function to check if given
// two intervals overlap
static boolean doOVerlap(Interval i1, Interval i2)
{
if (i1.low < i2.high && i2.low < i1.high)
return true;
return false;
}
// The main function that searches a given
// interval i in a given Interval Tree.
static Interval overlapSearch(ITNode root,
Interval i)
{
// Base Case, tree is empty
if (root == null)
return null;
// If given interval overlaps with root
if (doOVerlap(root.i, i))
return root.i;
// If left child of root is present
// and max of left child is greater
// than or equal to given interval,
// then i may overlap with an interval
// is left subtree
if (root.left != null &&
root.left.max >= i.low)
return overlapSearch(root.left, i);
// Else interval can only
// overlap with right subtree
return overlapSearch(root.right, i);
}
// This function prints all conflicting
// appointments in a given array of appointments.
static void printConflicting(Interval appt[], int n)
{
// Create an empty Interval Search
// Tree, add first appointment
ITNode root = null;
root = insert(root, appt[0]);
// Process rest of the intervals
for(int i = 1; i < n; i++)
{
// If current appointment conflicts
// with any of the existing intervals,
// print it
Interval res = overlapSearch(root, appt[i]);
if (res != null)
System.out.print("[" + appt[i].low +
"," + appt[i].high +
"] Conflicts with [" +
res.low + "," +
res.high + "]\n");
// Insert this appointment
root = insert(root, appt[i]);
}
}
// Driver code
public static void main(String[] args)
{
Interval appt[] = new Interval[6];
appt[0] = newNode(1, 5);
appt[1] = newNode(3, 7);
appt[2] = newNode(2, 6);
appt[3] = newNode(10, 15);
appt[4] = newNode(5, 6);
appt[5] = newNode(4, 100);
int n = appt.length;
System.out.print(
"Following are conflicting intervals\n");
printConflicting(appt, n);
}
}
// This code is contributed by tushar_bansal
# Python3 program to print all conflicting
# appointments in a given set of appointments
# Structure to represent an interval
class Interval:
def __init__(self):
self.low = None
self.high = None
# Structure to represent a node
# in Interval Search Tree
class ITNode:
def __init__(self):
self.max = None
self.i = None
self.left = None
self.right = None
def newNode(j):
#print(j)
temp = ITNode()
temp.i = j
temp.max = j[1]
return temp
# A utility function to check if
# given two intervals overlap
def doOVerlap(i1, i2):
if (i1[0] < i2[1] and i2[0] < i1[1]):
return True
return False
# Function to create a new node
def insert(node, data):
global succ
# If the tree is empty, return a new node
root = node
if (node == None):
return newNode(data)
# If key is smaller than root's key, go to left
# subtree and set successor as current node
# print(node)
if (data[0] < node.i[0]):
# print(node)
root.left = insert(node.left, data)
# Go to right subtree
else:
root.right = insert(node.right, data)
if root.max < data[1]:
root.max = data[1]
return root
# The main function that searches a given
# interval i in a given Interval Tree.
def overlapSearch(root, i):
# Base Case, tree is empty
if (root == None):
return None
# If given interval overlaps with root
if (doOVerlap(root.i, i)):
return root.i
# If left child of root is present and
# max of left child is greater than or
# equal to given interval, then i may
# overlap with an interval is left subtree
if (root.left != None and root.left.max >= i[0]):
return overlapSearch(root.left, i)
# Else interval can only overlap
# with right subtree
return overlapSearch(root.right, i)
# This function prints all conflicting
# appointments in a given array of
# appointments.
def printConflicting(appt, n):
# Create an empty Interval Search Tree,
# add first appointment
root = None
root = insert(root, appt[0])
# Process rest of the intervals
for i in range(1, n):
# If current appointment conflicts
# with any of the existing intervals,
# print it
res = overlapSearch(root, appt[i])
if (res != None):
print("[", appt[i][0], ",", appt[i][1],
"] Conflicts with [", res[0],
",", res[1], "]")
# Insert this appointment
root = insert(root, appt[i])
# Driver code
if __name__ == '__main__':
# Let us create interval tree
# shown in above figure
appt = [ [ 1, 5 ], [ 3, 7 ],
[ 2, 6 ], [ 10, 15 ],
[ 5, 6 ], [ 4, 100 ] ]
n = len(appt)
print("Following are conflicting intervals")
printConflicting(appt, n)
# This code is contributed by mohit kumar 29
// C# program to print all conflicting
// appointments in a given set of appointments
using System;
public class GfG
{
// Structure to represent an interval
public
class Interval
{
public
int low, high;
}
public
class ITNode
{
// 'i' could also be a normal variable
public
Interval i;
public
int max;
public
ITNode left, right;
}
// A utility function to create a new node
static Interval newNode(int l, int h)
{
Interval temp = new Interval();
temp.low = l;
temp.high = h;
return temp;
}
// A utility function to create a new node
static ITNode newNode(Interval i)
{
ITNode temp = new ITNode();
temp.i = i;
temp.max = i.high;
temp.left = temp.right = null;
return temp;
}
// A utility function to insert a new
// Interval Search Tree Node. This is
// similar to BST Insert. Here the
// low value of interval is used to
// maintain BST property
static ITNode insert(ITNode root, Interval i)
{
// Base case: Tree is empty,
// new node becomes root
if (root == null)
return newNode(i);
// Get low value of interval at root
int l = root.i.low;
// If root's low value is smaller,
// then new interval goes to left subtree
if (i.low < l)
root.left = insert(root.left, i);
// Else, new node goes to right subtree.
else
root.right = insert(root.right, i);
// Update the max value of this
// ancestor if needed
if (root.max < i.high)
root.max = i.high;
return root;
}
// A utility function to check if given
// two intervals overlap
static bool doOVerlap(Interval i1, Interval i2)
{
if (i1.low < i2.high && i2.low < i1.high)
return true;
return false;
}
// The main function that searches a given
// interval i in a given Interval Tree.
static Interval overlapSearch(ITNode root,
Interval i)
{
// Base Case, tree is empty
if (root == null)
return null;
// If given interval overlaps with root
if (doOVerlap(root.i, i))
return root.i;
// If left child of root is present
// and max of left child is greater
// than or equal to given interval,
// then i may overlap with an interval
// is left subtree
if (root.left != null &&
root.left.max >= i.low)
return overlapSearch(root.left, i);
// Else interval can only
// overlap with right subtree
return overlapSearch(root.right, i);
}
// This function prints all conflicting
// appointments in a given array of appointments.
static void printConflicting(Interval []appt, int n)
{
// Create an empty Interval Search
// Tree, add first appointment
ITNode root = null;
root = insert(root, appt[0]);
// Process rest of the intervals
for(int i = 1; i < n; i++)
{
// If current appointment conflicts
// with any of the existing intervals,
// print it
Interval res = overlapSearch(root, appt[i]);
if (res != null)
Console.Write("[" + appt[i].low +
"," + appt[i].high +
"] Conflicts with [" +
res.low + "," +
res.high + "]\n");
// Insert this appointment
root = insert(root, appt[i]);
}
}
// Driver code
public static void Main(String[] args)
{
Interval []appt = new Interval[6];
appt[0] = newNode(1, 5);
appt[1] = newNode(3, 7);
appt[2] = newNode(2, 6);
appt[3] = newNode(10, 15);
appt[4] = newNode(5, 6);
appt[5] = newNode(4, 100);
int n = appt.Length;
Console.Write(
"Following are conflicting intervals\n");
printConflicting(appt, n);
}
}
// This code is contributed by gauravrajput1
<script>
// Javascript program to print all conflicting
// appointments in a given set of appointments
// Structure to represent an interval
class Interval
{
constructor()
{
this.low = 0;
this.high = 0;
}
}
class ITNode
{
// 'i' could also be a normal variable
constructor()
{
this.max = 0;
this.left = null;
this.right = null;
this.i = null;
}
}
// A utility function to create a new node
function newNodeDouble(l, h)
{
var temp = new Interval();
temp.low = l;
temp.high = h;
return temp;
}
// A utility function to create a new node
function newNodeSingle(i)
{
var temp = new ITNode();
temp.i = i;
temp.max = i.high;
temp.left = temp.right = null;
return temp;
}
// A utility function to insert a new
// Interval Search Tree Node. This is
// similar to BST Insert. Here the
// low value of interval is used to
// maintain BST property
function insert(root, i)
{
// Base case: Tree is empty,
// new node becomes root
if (root == null)
return newNodeSingle(i);
// Get low value of interval at root
var l = root.i.low;
// If root's low value is smaller,
// then new interval goes to left subtree
if (i.low < l)
root.left = insert(root.left, i);
// Else, new node goes to right subtree.
else
root.right = insert(root.right, i);
// Update the max value of this
// ancestor if needed
if (root.max < i.high)
root.max = i.high;
return root;
}
// A utility function to check if given
// two intervals overlap
function doOVerlap(i1, i2)
{
if (i1.low < i2.high && i2.low < i1.high)
return true;
return false;
}
// The main function that searches a given
// interval i in a given Interval Tree.
function overlapSearch(root, i)
{
// Base Case, tree is empty
if (root == null)
return null;
// If given interval overlaps with root
if (doOVerlap(root.i, i))
return root.i;
// If left child of root is present
// and max of left child is greater
// than or equal to given interval,
// then i may overlap with an interval
// is left subtree
if (root.left != null &&
root.left.max >= i.low)
return overlapSearch(root.left, i);
// Else interval can only
// overlap with right subtree
return overlapSearch(root.right, i);
}
// This function prints all conflicting
// appointments in a given array of appointments.
function printConflicting(appt, n)
{
// Create an empty Interval Search
// Tree, add first appointment
var root = null;
root = insert(root, appt[0]);
// Process rest of the intervals
for(var i = 1; i < n; i++)
{
// If current appointment conflicts
// with any of the existing intervals,
// print it
var res = overlapSearch(root, appt[i]);
if (res != null)
document.write("[" + appt[i].low +
"," + appt[i].high +
"] Conflicts with [" +
res.low + "," +
res.high + "]<br>");
// Insert this appointment
root = insert(root, appt[i]);
}
}
// Driver code
var appt = Array(6);
appt[0] = newNodeDouble(1, 5);
appt[1] = newNodeDouble(3, 7);
appt[2] = newNodeDouble(2, 6);
appt[3] = newNodeDouble(10, 15);
appt[4] = newNodeDouble(5, 6);
appt[5] = newNodeDouble(4, 100);
var n = appt.length;
document.write(
"Following are conflicting intervals<br>");
printConflicting(appt, n);
</script>
Output
Following are conflicting intervals [3,7] Conflicts with [1,5] [2,6] Conflicts with [1,5] [5,6] Conflicts with [3,7] [4,100] Conflicts with [1,5]
Note that the above implementation uses a simple Binary Search Tree insert operations. Therefore, the time complexity of the above implementation is more than O(nLogn). We can use Red-Black Tree or AVL Tree balancing techniques to make the above implementation O(nLogn).
Auxiliary Space: O(h), Here h is the height of the tree. The extra space is used due to recursion call stack.