Related Articles

# Maximum Length Chain of Pairs | DP-20

• Difficulty Level : Medium
• Last Updated : 03 Aug, 2021

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

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 not 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++

 `// CPP program for above approach``#include ``using` `namespace` `std;` `// Structure for a Pair``class` `Pair``{``    ``public``:``    ``int` `a;``    ``int` `b;``};` `// This function assumes that arr[]``// is sorted in increasing order``// according the first``// (or smaller) values in Pairs.``int` `maxChainLength( Pair arr[], ``int` `n)``{``    ``int` `i, j, max = 0;``    ``int` `*mcl = ``new` `int``[``sizeof``( ``int` `) * n ];``    ` `    ``/* Initialize MCL (max chain length)``    ``values for all indexes */``    ``for` `( i = 0; i < n; i++ )``        ``mcl[i] = 1;``    ` `    ``/* Compute optimized chain``    ``length values in bottom up manner */``    ``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;``    ` `    ``// mcl[i] now stores the maximum``    ``// chain length ending with Pair i``    ` `    ``/* Pick maximum of all MCL values */``    ``for` `( i = 0; i < n; i++ )``        ``if` `( max < mcl[i] )``            ``max = mcl[i];``    ` `    ``/* Free memory to avoid memory leak */``    ` `    ``return` `max;``}``    `  `/* Driver code */``int` `main()``{``    ``Pair arr[] = { {5, 24}, {15, 25},``                        ``{27, 40}, {50, 60} };``    ``int` `n = ``sizeof``(arr)/``sizeof``(arr);``    ``cout << ``"Length of maximum size chain is "``                  ``<< maxChainLength( arr, n );``    ``return` `0;``}` `// This code is contributed by rathbhupendra`

## C

 `#include``#include` `// Structure for a pair``struct` `pair``{``  ``int` `a;``  ``int` `b;``};` `// This function assumes that``// arr[] is sorted in increasing order``// according the first``// (or smaller) values in pairs.``int` `maxChainLength( ``struct` `pair arr[], ``int` `n)``{``   ``int` `i, j, max = 0;``   ``int` `*mcl = (``int``*) ``malloc` `( ``sizeof``( ``int` `) * n );` `   ``/* Initialize MCL (max chain``     ``length) values for all indexes */``   ``for` `( i = 0; i < n; i++ )``      ``mcl[i] = 1;` `   ``/* Compute optimized chain length``   ``values in bottom up manner */``   ``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;` `   ``// mcl[i] now stores the maximum``   ``// chain length ending with pair i``  ` `   ``/* Pick maximum of all MCL values */``   ``for` `( i = 0; i < n; i++ )``      ``if` `( max < mcl[i] )``         ``max = mcl[i];` `   ``/* Free memory to avoid memory leak */``   ``free``( mcl );` `   ``return` `max;``}`  `/* Driver program to test above function */``int` `main()``{``    ``struct` `pair arr[] = { {5, 24}, {15, 25},``                          ``{27, 40}, {50, 60} };``    ``int` `n = ``sizeof``(arr)/``sizeof``(arr);``    ``printf``(``"Length of maximum size chain is %d\n"``,``           ``maxChainLength( arr, n ));``    ``return` `0;``}`

## Java

 `// Java program for above approach``class` `Pair``{``    ``int` `a;``    ``int` `b;``    ` `    ``public` `Pair(``int` `a, ``int` `b)``    ``{``        ``this``.a = a;``        ``this``.b = b;``    ``}``    ` `    ``// This function assumes that``    ``// arr[] is sorted in increasing order``    ``// according the first (or smaller)``    ``// values in pairs.``    ``static` `int` `maxChainLength(Pair arr[], ``int` `n)``    ``{``       ``int` `i, j, max = ``0``;``       ``int` `mcl[] = ``new` `int``[n];``     ` `       ``/* Initialize MCL (max chain length)``        ``values for all indexes */``       ``for` `( i = ``0``; i < n; i++ )``          ``mcl[i] = ``1``;``     ` `       ``/* Compute optimized chain length``        ``values in bottom up manner */``       ``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``;``     ` `       ``// mcl[i] now stores the maximum``       ``// chain length ending with pair i``     ` `       ``/* Pick maximum of all MCL values */``       ``for` `( i = ``0``; i < n; i++ )``          ``if` `( max < mcl[i] )``             ``max = mcl[i];``     ` `       ``return` `max;``    ``}` `    ``/* Driver program to test above function */``    ``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

 `# Python program for above approach``class` `Pair(``object``):``    ``def` `__init__(``self``, a, b):``        ``self``.a ``=` `a``        ``self``.b ``=` `b` `# This function assumes``# that arr[] is sorted in increasing``# order according the``# first (or smaller) values in pairs.``def` `maxChainLength(arr, n):``    ` `    ``max` `=` `0` `    ``# Initialize MCL(max chain``    ``# length) values for all indices``    ``mcl ``=` `[``1` `for` `i ``in` `range``(n)]` `    ``# Compute optimized chain``    ``# length values in bottom up manner``    ``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` `    ``# mcl[i] now stores the maximum``    ``# chain length ending with pair i` `    ``# Pick maximum of all MCL values``    ``for` `i ``in` `range``(n):``        ``if` `(``max` `< mcl[i]):``            ``max` `=` `mcl[i]` `    ``return` `max` `# Driver program to test above function``arr ``=` `[Pair(``5``, ``24``), Pair(``15``, ``25``),``       ``Pair(``27``, ``40``), Pair(``50``, ``60``)]` `print``(``'Length of maximum size chain is'``,``      ``maxChainLength(arr, ``len``(arr)))` `# This code is contributed by Soumen Ghosh`

## C#

 `// Dynamic C# program to find``// Maximum Length Chain of Pairs``using` `System;` `class` `Pair``{``    ``int` `a;``    ``int` `b;``    ` `    ``public` `Pair(``int` `a, ``int` `b)``    ``{``        ``this``.a = a;``        ``this``.b = b;``    ``}``    ` `    ``// This function assumes that arr[]``    ``// is sorted in increasing order``    ``// according the first (or smaller)``    ``// values in pairs.``    ``static` `int` `maxChainLength(Pair []arr, ``int` `n)``    ``{``        ``int` `i, j, max = 0;``        ``int` `[]mcl = ``new` `int``[n];``        ` `        ``// Initialize MCL (max chain length)``        ``// values for all indexes``        ``for``(i = 0; i < n; i++ )``            ``mcl[i] = 1;``        ` `        ``// Compute optimized chain length``        ``// values in bottom up manner``        ``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] now stores the maximum``          ``// chain length ending with pair i``          ``mcl[i] = mcl[j] + 1;` `        ``// Pick maximum of all MCL values``        ``for` `( i = 0; i < n; i++ )``            ``if` `(max < mcl[i] )``                ``max = mcl[i];``        ` `        ``return` `max;``    ``}` `    ``// Driver Code``    ``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));``    ``}``}` `// This code is contributed by nitin mittal.`

## Javascript

 ``
Output
`Length of maximum size chain is 3`

Time Complexity: O(n^2) where n is the number of pairs.

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.

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 + memorization).
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:

## CPP14

 `// CPP program for above approach``#include ``using` `namespace` `std;` `// Structure val``struct` `val``{``    ``int` `first;``    ``int` `second;``};` `map, ``int``> m;` `// Memoisation function``int` `findMaxChainLen(``struct` `val p[], ``int` `n,``                        ``int` `prev, ``int` `pos)``{``    ` `    ``// Check if pair { pos, prev } exists``    ``// in m``    ``if` `(m.find({ pos, prev }) != m.end())``    ``{``        ``return` `m[{ pos, prev }];``    ``}` `    ``// Check if pos is >=n``    ``if` `(pos >= n)``        ``return` `0;` `    ``// Check if p[pos].first is``    ``// less than prev``    ``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;``    ``}``}` `// Function to calculate maximum``// chain length``int` `maxChainLen(``struct` `val p[], ``int` `n)``{``    ``m.clear();``  ` `    ``// Call memoisation function``    ``int` `ans = findMaxChainLen(p, n, 0, 0);``    ``return` `ans;``}` `// Driver Code``int` `main()``{` `    ``int` `n = 5;``    ``val p[n];``    ``p.first = 5;``    ``p.second = 24;` `    ``p.first = 39;``    ``p.second = 60;` `    ``p.first = 15;``    ``p.second = 28;` `    ``p.first = 27;``    ``p.second = 40;` `    ``p.first = 50;``    ``p.second = 90;``    ` `    ``// Function Call``    ``cout << maxChainLen(p, n) << endl;``    ``return` `0;``}`

Output
`3`

-HIXptqM3Q