Maximum Length Chain of Pairs | DP-20
Last Updated :
12 Apr, 2023
You are given n pairs of numbers. In every pair, the first number is always smaller than the second number. A pair (c, d) can follow another pair (a, b) if b < c. Chain of pairs can be formed in this fashion. Find the longest chain which can be formed from a given set of pairs.
Source: Amazon Interview | Set 2
For example, if the given pairs are {{5, 24}, {39, 60}, {15, 28}, {27, 40}, {50, 90} }, then the longest chain that can be formed is of length 3, and the chain is {{5, 24}, {27, 40}, {50, 90}}
Method 1: This problem is a variation of standard Longest Increasing Subsequence problem. Following is a simple two step process.
1) Sort given pairs in increasing order of first (or smaller) element. Why do we need sorting? Consider the example {{6, 8}, {3, 4}} to understand the need of sorting. If we proceed to second step without sorting, we get output as 1. But the correct output is 2.
2) Now run a modified LIS process where we compare the second element of already finalized LIS with the first element of new LIS being constructed.
The following code is a slight modification of method 2 of this post.
C++
#include <bits/stdc++.h>
using namespace std;
class Pair
{
public :
int a;
int b;
};
int maxChainLength( Pair arr[], int n)
{
int i, j, max = 0;
int *mcl = new int [ sizeof ( int ) * n ];
for ( i = 0; i < n; i++ )
mcl[i] = 1;
for ( i = 1; i < n; i++ )
for ( j = 0; j < i; j++ )
if ( arr[i].a > arr[j].b &&
mcl[i] < mcl[j] + 1)
mcl[i] = mcl[j] + 1;
for ( i = 0; i < n; i++ )
if ( max < mcl[i] )
max = mcl[i];
return max;
}
int main()
{
Pair arr[] = { {5, 24}, {15, 25},
{27, 40}, {50, 60} };
int n = sizeof (arr)/ sizeof (arr[0]);
cout << "Length of maximum size chain is "
<< maxChainLength( arr, n );
return 0;
}
|
C
#include<stdio.h>
#include<stdlib.h>
struct pair
{
int a;
int b;
};
int maxChainLength( struct pair arr[], int n)
{
int i, j, max = 0;
int *mcl = ( int *) malloc ( sizeof ( int ) * n );
for ( i = 0; i < n; i++ )
mcl[i] = 1;
for ( i = 1; i < n; i++ )
for ( j = 0; j < i; j++ )
if ( arr[i].a > arr[j].b &&
mcl[i] < mcl[j] + 1)
mcl[i] = mcl[j] + 1;
for ( i = 0; i < n; i++ )
if ( max < mcl[i] )
max = mcl[i];
free ( mcl );
return max;
}
int main()
{
struct pair arr[] = { {5, 24}, {15, 25},
{27, 40}, {50, 60} };
int n = sizeof (arr)/ sizeof (arr[0]);
printf ( "Length of maximum size chain is %d\n" ,
maxChainLength( arr, n ));
return 0;
}
|
Java
import java.io.*;
class Pair {
int a;
int b;
public Pair( int a, int b)
{
this .a = a;
this .b = b;
}
static int maxChainLength(Pair arr[], int n)
{
int i, j, max = 0 ;
int mcl[] = new int [n];
for (i = 0 ; i < n; i++)
mcl[i] = 1 ;
for (i = 1 ; i < n; i++)
for (j = 0 ; j < i; j++)
if (arr[i].a > arr[j].b
&& mcl[i] < mcl[j] + 1 )
mcl[i] = mcl[j] + 1 ;
for (i = 0 ; i < n; i++)
if (max < mcl[i])
max = mcl[i];
return max;
}
public static void main(String[] args)
{
Pair arr[] = new Pair[] { new Pair( 5 , 24 ),
new Pair( 15 , 25 ),
new Pair( 27 , 40 ),
new Pair( 50 , 60 ) };
System.out.println(
"Length of maximum size chain is "
+ maxChainLength(arr, arr.length));
}
}
|
Python3
class Pair( object ):
def __init__( self , a, b):
self .a = a
self .b = b
def maxChainLength(arr, n):
max = 0
mcl = [ 1 for i in range (n)]
for i in range ( 1 , n):
for j in range ( 0 , i):
if (arr[i].a > arr[j].b and
mcl[i] < mcl[j] + 1 ):
mcl[i] = mcl[j] + 1
for i in range (n):
if ( max < mcl[i]):
max = mcl[i]
return max
arr = [Pair( 5 , 24 ), Pair( 15 , 25 ),
Pair( 27 , 40 ), Pair( 50 , 60 )]
print ( 'Length of maximum size chain is' ,
maxChainLength(arr, len (arr)))
|
C#
using System;
class Pair
{
int a;
int b;
public Pair( int a, int b)
{
this .a = a;
this .b = b;
}
static int maxChainLength(Pair []arr, int n)
{
int i, j, max = 0;
int []mcl = new int [n];
for (i = 0; i < n; i++ )
mcl[i] = 1;
for (i = 1; i < n; i++)
for (j = 0; j < i; j++)
if (arr[i].a > arr[j].b &&
mcl[i] < mcl[j] + 1)
mcl[i] = mcl[j] + 1;
for ( i = 0; i < n; i++ )
if (max < mcl[i] )
max = mcl[i];
return max;
}
public static void Main()
{
Pair []arr = new Pair[]
{ new Pair(5,24), new Pair(15, 25),
new Pair (27, 40), new Pair(50, 60)};
Console.Write("Length of maximum size
chain is " +
maxChainLength(arr, arr.Length));
}
}
|
Javascript
<script>
class Pair
{
constructor(a,b)
{
this .a=a;
this .b=b;
}
}
function maxChainLength(arr,n)
{
let i, j, max = 0;
let mcl = new Array(n);
for ( i = 0; i < n; i++ )
mcl[i] = 1;
for ( i = 1; i < n; i++ )
for ( j = 0; j < i; j++ )
if ( arr[i].a > arr[j].b &&
mcl[i] < mcl[j] + 1)
mcl[i] = mcl[j] + 1;
for ( i = 0; i < n; i++ )
if ( max < mcl[i] )
max = mcl[i];
return max;
}
let arr=[ new Pair(5,24),
new Pair(15, 25),
new Pair (27, 40),
new Pair(50, 60)];
document.write( "Length of maximum size chain is " +
maxChainLength(arr, arr.length));
</script>
|
Output
Length of maximum size chain is 3
Time Complexity: O(n^2) where n is the number of pairs.
Auxiliary Space: O(n) because of the extra array used to store maximum chain length.
The given problem is also a variation of Activity Selection problem and can be solved in (nLogn) time. To solve it as a activity selection problem, consider the first element of a pair as start time in activity selection problem, and the second element of pair as end time.
Method 2:
- Sort given pairs in increasing order of second values.
- Take ans = 0 initially and prev = INT_MIN.
- Now iterate on the given array and if arr[i].first>prev , then increase answer and set prev=arr[i].second.
- Finally return answer.
C++
#include <bits/stdc++.h>
using namespace std;
struct val
{
int first;
int second;
};
bool static comp(val fst, val sec){
return fst.second<sec.second;
}
int maxChainLen( struct val p[], int n){
sort(p,p+n,comp);
int prev=-1e9;
int ans=0;
for ( int i=0;i<n;i++){
if (p[i].first>prev){
ans++;
prev=p[i].second;
}
}
return ans;
}
int main() {
int n = 5;
val p[n];
p[0].first = 5;
p[0].second = 24;
p[1].first = 39;
p[1].second = 60;
p[2].first = 15;
p[2].second = 28;
p[3].first = 27;
p[3].second = 40;
p[4].first = 50;
p[4].second = 90;
cout << maxChainLen(p, n) << endl;
return 0;
}
|
Java
import java.util.*;
import java.io.*;
class GFG {
public static int maxChainLen( int p[][], int n) {
Arrays.sort(p, new C());
int prev = - 1000000000 ;
int ans = 0 ;
for ( int i = 0 ; i < n; i++) {
if (p[i][ 0 ] > prev) {
ans++;
prev = p[i][ 1 ];
}
}
return ans;
}
public static class C implements Comparator< int []> {
public int compare( int [] a1, int [] a2) {
return Integer.compare(a1[ 1 ], a2[ 1 ]);
}
}
public static void main (String[] args) {
int n = 5 ;
int [][] p = {{ 5 , 24 }, { 39 , 60 }, { 15 , 28 }, { 27 , 40 }, { 50 , 90 }};
System.out.println(maxChainLen(p, n));
}
}
|
Python3
from typing import List , Tuple
def max_chain_len(p: List [ Tuple [ int , int ]]) - > int :
p.sort(key = lambda x: x[ 1 ])
prev = - 1e9
ans = 0
for x in p:
if x[ 0 ] > prev:
ans + = 1
prev = x[ 1 ]
return ans
n = 5
p = [
( 5 , 24 ),
( 39 , 60 ),
( 15 , 28 ),
( 27 , 40 ),
( 50 , 90 )
]
print (max_chain_len(p))
|
C#
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
class GFG
{
public static int MaxChainLen( int [][] p, int n)
{
Array.Sort(p, new C());
int prev = -1000000000;
int ans = 0;
for ( int i = 0; i < n; i++)
{
if (p[i][0] > prev)
{
ans++;
prev = p[i][1];
}
}
return ans;
}
public class C : IComparer< int []>
{
public int Compare( int [] a1, int [] a2)
{
return Comparer< int >.Default.Compare(a1[1], a2[1]);
}
}
static void Main( string [] args)
{
int n = 5;
int [][] p = {
new int [] { 5, 24 },
new int [] { 39, 60 },
new int [] { 15, 28 },
new int [] { 27, 40 },
new int [] { 50, 90 }
};
Console.WriteLine(MaxChainLen(p, n));
}
}
|
Javascript
function maxChainLen(p) {
p.sort((a, b) => a[1] - b[1]);
let prev = -1e9;
let ans = 0;
for (const x of p) {
if (x[0] > prev) {
ans += 1;
prev = x[1];
}
}
return ans;
}
const n = 5;
const p = [ [5, 24],
[39, 60],
[15, 28],
[27, 40],
[50, 90]
];
console.log(maxChainLen(p));
|
Time Complexity: O(n*log2n).
Auxiliary Space: O(1) as no extra space has been used.
Another approach( Top-down Dynamic programming): Now we will explore the way of solving this problem using the top-down approach of dynamic programming (recursion + memoization).
Since we are going to solve the above problem using top down method our first step is to figure out the recurrence relation. The best and the easiest way to get the recurrence relation is to think about the choices that we have at each state or position.
If we look at the above problem carefully, we find two choices to be present at each position/index. The two choices are:
Choice 1: To select the element at the particular position and explore the rest, (or)
Choice 2: To leave the element at that position and explore the rest.
Please note here that we can select the element at a particular position only if first element at that position is greater than the second element that we have previously chosen (this is a constraint given in the question). Hence, in the recursion we maintain a variable which would tell us the previous element that we picked.
Also, we have to maximize our answer. Hence, we have to find out the maximum resulting option by exploring the above two choices at each position.
The resulting recurrence relation would be:
??T(n) = max( maxlenchain(p,n,p[pos].second,0)+1,maxlenchain(p,n,prev_choosen_ele,pos+1) )
Please note the function signature is as follows:
int cal(struct val p[],int n,int prev_choosen_ele,int pos);
Nevertheless, we should not forget our base condition in recursion. If not, our code would enjoy a vacation by just executing forever and not stopping at all.
So, our base condition for this problem is quite simple. If we reach the end of our exploration, we just return 0, as no more chains would be possible.
??if(pos >= n) return 0;
To avoid the repetitive task, we do the dynamic programming magic (It is a magic to reduce your time complexity). We store the position and previous element in a map. If we ever happened to come to the same position with the same previous element we do not recompute again. We just return the answer from the map.
Below is the implementation of the above approach:
C++14
#include <bits/stdc++.h>
using namespace std;
struct val
{
int first;
int second;
};
map<pair< int , int >, int > m;
int findMaxChainLen( struct val p[], int n,
int prev, int pos)
{
if (m.find({ pos, prev }) != m.end())
{
return m[{ pos, prev }];
}
if (pos >= n)
return 0;
if (p[pos].first <= prev)
{
return findMaxChainLen(p, n, prev,
pos + 1);
}
else
{
int ans = max(findMaxChainLen(p, n,
p[pos].second, 0) + 1,
findMaxChainLen(p, n,
prev, pos + 1));
m[{ pos, prev }] = ans;
return ans;
}
}
int maxChainLen( struct val p[], int n)
{
m.clear();
int ans = findMaxChainLen(p, n, 0, 0);
return ans;
}
int main()
{
int n = 5;
val p[n];
p[0].first = 5;
p[0].second = 24;
p[1].first = 39;
p[1].second = 60;
p[2].first = 15;
p[2].second = 28;
p[3].first = 27;
p[3].second = 40;
p[4].first = 50;
p[4].second = 90;
cout << maxChainLen(p, n) << endl;
return 0;
}
|
Java
import java.util.*;
class GFG{
static class val
{
int first;
int second;
};
static class pair
{
int first, second;
public pair( int first, int second)
{
this .first = first;
this .second = second;
}
@Override
public int hashCode()
{
final int prime = 31 ;
int result = 1 ;
result = prime * result + first;
result = prime * result + second;
return result;
}
@Override
public boolean equals(Object obj)
{
if ( this == obj)
return true ;
if (obj == null )
return false ;
if (getClass() != obj.getClass())
return false ;
pair other = (pair) obj;
if (first != other.first)
return false ;
if (second != other.second)
return false ;
return true ;
}
}
static Map<pair, Integer> m = new HashMap<>();
static int findMaxChainLen(val p[], int n,
int prev, int pos)
{
if (m.containsKey( new pair(pos, prev)))
{
return m.get( new pair(pos, prev));
}
if (pos >= n)
return 0 ;
if (p[pos].first <= prev)
{
return findMaxChainLen(p, n, prev,
pos + 1 );
}
else
{
int ans = Math.max(findMaxChainLen(
p, n, p[pos].second, 0 ) + 1 ,
findMaxChainLen(
p, n, prev, pos + 1 ));
m.put( new pair(pos, prev), ans);
return ans;
}
}
static int maxChainLen(val p[], int n)
{
m.clear();
int ans = findMaxChainLen(p, n, 0 , 0 );
return ans;
}
public static void main(String[] args)
{
int n = 5 ;
val []p = new val[n];
for ( int i = 0 ; i < n; i++)
p[i] = new val();
p[ 0 ].first = 5 ;
p[ 0 ].second = 24 ;
p[ 1 ].first = 39 ;
p[ 1 ].second = 60 ;
p[ 2 ].first = 15 ;
p[ 2 ].second = 28 ;
p[ 3 ].first = 27 ;
p[ 3 ].second = 40 ;
p[ 4 ].first = 50 ;
p[ 4 ].second = 90 ;
System.out.print(maxChainLen(p, n) + "\n" );
}
}
|
Python3
class val:
def __init__( self ,first,second):
self .first = first
self .second = second
def findMaxChainLen(p, n, prev, pos):
global m
if (val(pos, prev) in m):
return m[val(pos, prev)]
if (pos > = n):
return 0
if (p[pos].first < = prev):
return findMaxChainLen(p, n, prev, pos + 1 )
else :
ans = max (findMaxChainLen(p, n,
p[pos].second, 0 ) + 1 ,
findMaxChainLen(p, n,
prev, pos + 1 ))
m[val(pos, prev)] = ans
return ans
def maxChainLen(p,n):
global m
m.clear()
ans = findMaxChainLen(p, n, 0 , 0 )
return ans
n = 5
p = [ 0 ] * n
p[ 0 ] = val( 5 , 24 )
p[ 1 ] = val( 39 , 60 )
p[ 2 ] = val( 15 , 28 )
p[ 3 ] = val( 27 , 40 )
p[ 4 ] = val( 50 , 90 )
m = {}
print (maxChainLen(p, n))
|
C#
using System;
using System.Collections.Generic;
class GFG{
class val
{
public int first;
public int second;
};
class pair
{
public int first, second;
public pair( int first, int second)
{
this .first = first;
this .second = second;
}
public override int GetHashCode()
{
int prime = 31;
int result = 1;
result = prime * result + first;
result = prime * result + second;
return result;
}
public bool Equals(pair other)
{
return other != null && (other.first == first) && (other.second == second);
}
}
static Dictionary<pair, int > m = new Dictionary<pair, int >();
static int findMaxChainLen(val[] p, int n,
int prev, int pos)
{
if (m.ContainsKey( new pair(pos, prev)))
{
return m[ new pair(pos, prev)];
}
if (pos >= n)
return 0;
if (p[pos].first <= prev)
{
return findMaxChainLen(p, n, prev,
pos + 1);
}
else
{
int ans = Math.Max(findMaxChainLen(
p, n, p[pos].second, 0) + 1,
findMaxChainLen(
p, n, prev, pos + 1));
m[ new pair(pos, prev)] = ans;
return ans;
}
}
static int maxChainLen(val[] p, int n)
{
m.Clear();
int ans = findMaxChainLen(p, n, 0, 0);
return ans;
}
public static void Main( string [] args)
{
int n = 5;
val []p = new val[n];
for ( int i = 0; i < n; i++)
p[i] = new val();
p[0].first = 5;
p[0].second = 24;
p[1].first = 39;
p[1].second = 60;
p[2].first = 15;
p[2].second = 28;
p[3].first = 27;
p[3].second = 40;
p[4].first = 50;
p[4].second = 90;
Console.WriteLine(maxChainLen(p, n) + "\n" );
}
}
|
Javascript
<script>
class val
{
constructor(first,second){
this .first = first;
this .second = second;
}
};
let m = new Map();
function findMaxChainLen(p,n,prev,pos)
{
if (m.has( new val(pos, prev)))
return m.get( new val(pos, prev));
if (pos >= n)
return 0;
if (p[pos].first <= prev)
{
return findMaxChainLen(p, n, prev,
pos + 1);
}
else
{
let ans = Math.max(findMaxChainLen(p, n,
p[pos].second, 0) + 1,
findMaxChainLen(p, n,
prev, pos + 1));
m.set( new val(pos, prev),ans);
return ans;
}
}
function maxChainLen(p,n)
{
m.clear();
let ans = findMaxChainLen(p, n, 0, 0);
return ans;
}
let n = 5;
let p = new Array(n);
p[0] = new val(5,24);
p[1] = new val(39,60);
p[2] = new val(15,28);
p[3] = new val(27,40);
p[4] = new val(50,90);
document.write(maxChainLen(p, n), "</br>" );
</script>
|
Time Complexity: O(n2).
Auxiliary Space: O(n2), due to the use of a map to store previously calculated values.
Similar Reads
Maximum Length Chain of Pairs | Set-2
Given an array of pairs of numbers of size N. In every pair, the first number is always smaller than the second number. A pair (c, d) can follow another pair (a, b) if b < c. The chain of pairs can be formed in this fashion. The task is to find the length of the longest chain which can be formed
7 min read
Print Maximum Length Chain of Pairs
You are given n pairs of numbers. In every pair, the first number is always smaller than the second number. A pair (c, d) can follow another pair (a, b) if b < c. Chain of pairs can be formed in this fashion. Find the longest chain which can be formed from a given set of pairs. Examples: Input: (
8 min read
Maximum AND value of a pair in an array
Given an array of N positive elements, the task is to find the maximum AND value generated by any pair of elements from the array. Examples: Input: arr1[] = {16, 12, 8, 4}Output: 8Explanation: 8 AND12 will give us the maximum value 8 Input: arr1[] = {4, 8, 16, 2}Output: 0 Recommended PracticeMaximum
12 min read
Find maximum length Snake sequence
Given a grid of numbers, find maximum length Snake sequence and print it. If multiple snake sequences exists with the maximum length, print any one of them. A snake sequence is made up of adjacent numbers in the grid such that for each number, the number on the right or the number below it is +1 or
11 min read
Count ways of choosing a pair with maximum difference
Given an array of n integers, we need to find the no. of ways of choosing pairs with maximum difference. Examples: Input : a[] = {3, 2, 1, 1, 3} Output : 4 Explanation:- Here, the maximum difference you can find is 2 which is from (1, 3). No. of ways of choosing it: 1) Choosing the first and third e
8 min read
Maximum number of segments of lengths a, b and c
Given a positive integer N, find the maximum number of segments of lengths a, b and c that can be formed from N . Examples : Input : N = 7, a = 5, b, = 2, c = 5 Output : 2 N can be divided into 2 segments of lengths 2 and 5. For the second example, Input : N = 17, a = 2, b = 1, c = 3 Output : 17 N c
13 min read
Maximum Sum pair of non adjacent elements in array
Given an array arr[] of distinct Integers, find the pair with maximum sum such that both elements of the pair are not adjacent in the array Examples: Input: arr[] = {7, 3, 4, 1, 8, 9}Output: 9 7Explanation: Pair with maximum sum is (8, 9). But since both elements are adjacent, it is not a valid pair
8 min read
Find pair with maximum GCD in an array
We are given an array of positive integers. Find the pair in array with maximum GCD.Examples: Input : arr[] : { 1 2 3 4 5 }Output : 2Explanation : Pair {2, 4} has GCD 2 which is highest. Other pairs have a GCD of 1.Input : arr[] : { 2 3 4 8 8 11 12 }Output : 8Explanation : Pair {8, 8} has GCD 8 whic
15+ min read
Maximum Sum Subsequence of length k
Given an array sequence [A1, A2 ...An], the task is to find the maximum possible sum of increasing subsequence S of length k such that S1<=S2<=S3.........<=Sk. Examples: Input : n = 8 k = 3 A=[8 5 9 10 5 6 21 8] Output : 40 Possible Increasing subsequence of Length 3 with maximum possible s
11 min read
Find maximum sum array of length less than or equal to m
Given n arrays of different lengths consisting of integers, the target is to pick atmost one subarray from an array such that the combined length of all picked sub arrays does not become greater than m and also sum of their elements is maximum.(also given that value of n can not be more than 100) Pr
13 min read