Given N number of envelopes, as {W, H} pair, where W as the width and H as the height. One envelope can fit into another if and only if both the width and height of one envelope is greater than the width and height of the other envelope. Find the maximum number of envelopes that can be put inside another envelope and so on. Rotation of envelope is not allowed.

Examples:
Input: envelope[] = {{4, 3}, {5, 3}, {5, 6}, {1, 2}}
Output: 3
Explanation:
The maximum number of envelopes that can be put into another envelope
is 3.
({1, 2}, {4, 3}, {5, 6})
Input: envelope[] = {{3, 6}, {5, 4}, {4, 8}, {6, 9}, {10, 7}, {12, 12}}
Output: 4
Explanation:
The maximum number of envelopes that can be put into another envelope is 4.
({3, 6}, {4, 8}, {6, 9}, {12, 12})
Naive Approach: This problem is similar to the Longest Increasing Subsequence problem of Dynamic Programming. The idea is to sort the envelopes in non-decreasing order and for each envelope check the number of envelopes that can be put inside that envelope. Follow the steps below to solve the problem:
- Sort the array in the non-decreasing order of width and height.
- Initialize a dp[] array, where dp[i] stores the number of envelopes that can be put inside with envelope[i] as the largest envelope.
- For each envelope[i], loop through the envelopes smaller than itself and check if the width and the height of the smaller envelope is strictly less than that of envelope[i]. If it is less, than the smaller envelope can be put inside envelope[i].
- The maximum of the dp[] array gives the maximum number of envelopes that can be put inside one another.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int maxEnvelopes(vector<vector< int > > envelopes)
{
int N = envelopes.size();
if (N == 0)
return N;
sort(envelopes.begin(),
envelopes.end());
int dp[N];
int max_envelope = 1;
dp[0] = 1;
for ( int i = 1; i < N; ++i) {
dp[i] = 1;
for ( int j = 0; j < i; ++j) {
if (envelopes[i][0] > envelopes[j][0]
&& envelopes[i][1] > envelopes[j][1]
&& dp[i] < dp[j] + 1)
dp[i] = dp[j] + 1;
}
max_envelope = max(max_envelope,
dp[i]);
}
return max_envelope;
}
int main()
{
vector<vector< int > > envelopes
= { { 4, 3 }, { 5, 3 }, { 5, 6 }, { 1, 2 } };
cout << maxEnvelopes(envelopes);
return 0;
}
|
Java
import java.util.*;
import java.lang.*;
class GFG{
static int maxEnvelopes( int [][] envelopes)
{
int N = envelopes.length;
if (N == 0 )
return N;
Arrays.sort(envelopes,
(a, b) -> (a[ 0 ] != b[ 0 ]) ?
a[ 0 ] - b[ 0 ] :
a[ 1 ] - b[ 1 ]);
int [] dp = new int [N];
int max_envelope = 1 ;
dp[ 0 ] = 1 ;
for ( int i = 1 ; i < N; ++i)
{
dp[i] = 1 ;
for ( int j = 0 ; j < i; ++j)
{
if (envelopes[i][ 0 ] > envelopes[j][ 0 ] &&
envelopes[i][ 1 ] > envelopes[j][ 1 ] &&
dp[i] < dp[j] + 1 )
dp[i] = dp[j] + 1 ;
}
max_envelope = Math.max(max_envelope, dp[i]);
}
return max_envelope;
}
public static void main (String[] args)
{
int [][] envelopes = { { 4 , 3 }, { 5 , 3 },
{ 5 , 6 }, { 1 , 2 } };
System.out.println(maxEnvelopes(envelopes));
}
}
|
Python3
def maxEnvelopes(envelopes):
N = len (envelopes)
if (N = = 0 ):
return N
envelopes = sorted (envelopes)
dp = [ 0 ] * N
max_envelope = 1
dp[ 0 ] = 1
for i in range ( 1 , N):
dp[i] = 1
for j in range (i):
if (envelopes[i][ 0 ] > envelopes[j][ 0 ]
and envelopes[i][ 1 ] > envelopes[j][ 1 ]
and dp[i] < dp[j] + 1 ):
dp[i] = dp[j] + 1
max_envelope = max (max_envelope, dp[i])
return max_envelope
if __name__ = = '__main__' :
envelopes = [ [ 4 , 3 ], [ 5 , 3 ],
[ 5 , 6 ], [ 1 , 2 ] ]
print (maxEnvelopes(envelopes))
|
C#
using System;
using System.Collections;
using System.Collections.Generic;
class GFG
{
static int maxEnvelopes( int [][] envelopes)
{
int N = envelopes.Length;
if (N == 0){
return N;
}
Array.Sort(envelopes, new comp());
int [] dp = new int [N];
int max_envelope = 1;
dp[0] = 1;
for ( int i = 1 ; i < N ; ++i)
{
dp[i] = 1;
for ( int j = 0 ; j < i ; ++j)
{
if (envelopes[i][0] > envelopes[j][0] && envelopes[i][1] > envelopes[j][1] && dp[i] < dp[j] + 1){
dp[i] = dp[j] + 1;
}
}
max_envelope = Math.Max(max_envelope, dp[i]);
}
return max_envelope;
}
public static void Main( string [] args){
int [][] envelopes = new int [][]{
new int []{ 4, 3 },
new int []{ 5, 3 },
new int []{ 5, 6 },
new int []{ 1, 2 }
};
Console.WriteLine(maxEnvelopes(envelopes));
}
}
class comp : IComparer< int []>{
public int Compare( int [] a, int [] b)
{
if (a[0] != b[0]) return a[0] - b[0];
return a[1] - b[1];
}
}
|
Javascript
<script>
function maxEnvelopes(envelopes)
{
var N = envelopes.length;
if (N == 0)
return N;
envelopes.sort();
var dp = Array(N);
var max_envelope = 1;
dp[0] = 1;
for ( var i = 1; i < N; ++i) {
dp[i] = 1;
for ( var j = 0; j < i; ++j) {
if (envelopes[i][0] > envelopes[j][0]
&& envelopes[i][1] > envelopes[j][1]
&& dp[i] < dp[j] + 1)
dp[i] = dp[j] + 1;
}
max_envelope = Math.max(max_envelope,
dp[i]);
}
return max_envelope;
}
var envelopes
= [ [ 4, 3 ], [ 5, 3 ], [ 5, 6 ], [ 1, 2 ] ];
document.write( maxEnvelopes(envelopes));
</script>
|
Time Complexity: O(N2)
Auxiliary Space: O(N)
Efficient Approach:To optimize the naive approach the idea is to use the concept of Binary Search and Longest Increasing Subsequence. Sorting the envelopes in the increasing order of width and the decreasing order of height if width is same, reduces the problem to finding the longest increasing sequence of height of the envelope. This approach works as width is already sorted in increasing order and only maximum increasing sequence of height is sufficient to find the maximum number of envelopes. The efficient way to find the Longest Increasing Sequence in N×log(N) approach is discussed in this article.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int maxEnvelopes(vector<vector< int > >& envelopes)
{
int N = envelopes.size();
if (N == 0)
return N;
sort(envelopes.begin(), envelopes.end(),
[](vector< int >& a, vector< int >& b) {
return a[0] < b[0]
or (a[0] == b[0] and a[1] > b[1]);
});
vector< int > dp;
for ( int i = 0; i < N; ++i) {
auto iter = lower_bound(dp.begin(),
dp.end(),
envelopes[i][1]);
if (iter == dp.end())
dp.push_back(envelopes[i][1]);
else if (envelopes[i][1] < *iter)
*iter = envelopes[i][1];
}
return dp.size();
}
int main()
{
vector<vector< int > > envelopes
= { { 4, 3 }, { 5, 3 }, { 5, 6 }, { 1, 2 } };
cout << maxEnvelopes(envelopes);
return 0;
}
|
Java
import java.io.*;
import java.util.*;
import java.util.Arrays;
import java.util.Collections;
class GFG{
static int maxEnvelopes( int [][] envelopes)
{
int N = envelopes.length;
if (N == 0 )
return N;
Arrays.sort(envelopes, new Comparator< int []>() {
@Override
public int compare( int [] a,
int [] b)
{
return a[ 0 ] == b[ 0 ] ? b[ 1 ] - a[ 1 ] : a[ 0 ] - b[ 0 ];;
}
});
ArrayList<Integer> dp = new ArrayList<Integer>();
for ( int i = 0 ; i < N; ++i) {
int iter = Collections.binarySearch(dp, envelopes[i][ 1 ]);
if (iter < 0 )
iter=Math.abs(iter)- 1 ;
if (iter == dp.size())
dp.add(envelopes[i][ 1 ]);
else if (envelopes[i][ 1 ] < dp.get(iter))
dp.set(iter,envelopes[i][ 1 ]);
}
return dp.size();
}
public static void main (String[] args)
{
int [][] envelopes = { { 4 , 3 }, { 5 , 3 }, { 5 , 6 }, { 1 , 2 } };
System.out.println(maxEnvelopes(envelopes));
}
}
|
Python3
from bisect import bisect_left as lower_bound
def maxEnvelopes(envelopes):
N = len (envelopes)
if (N = = 0 ):
return N
envelopes.sort()
dp = []
for i in range (N):
iter = lower_bound(dp,envelopes[i][ 1 ])
if ( iter = = len (dp)):
dp.append(envelopes[i][ 1 ])
elif (envelopes[i][ 1 ] < dp[ iter ]):
dp[ iter ] = envelopes[i][ 1 ]
return len (dp)
envelopes = [[ 4 , 3 ], [ 5 , 3 ], [ 5 , 6 ], [ 1 , 2 ]]
print (maxEnvelopes(envelopes))
|
C#
using System;
using System.Linq;
using System.Collections.Generic;
class GFG
{
static int maxEnvelopes( int [][] envelopes)
{
int N = envelopes.Length;
if (N == 0)
return N;
Array.Sort(envelopes, (a, b) = > a[0] - b[0]);
List< int > dp = new List< int >();
for ( int i = 0; i < N; ++i) {
int iter = dp.BinarySearch(envelopes[i][1]);
if (iter < 0)
iter = ~iter;
if (iter == dp.Count)
dp.Add(envelopes[i][1]);
else if (envelopes[i][1] < dp[iter])
dp[iter] = envelopes[i][1];
}
return dp.Count;
}
static void Main( string [] args)
{
int [][] envelopes = new int [4][];
envelopes[0] = new int [] { 4, 3 };
envelopes[1] = new int [] { 5, 3 };
envelopes[2] = new int [] { 5, 6 };
envelopes[3] = new int [] { 1, 2 };
Console.WriteLine(maxEnvelopes(envelopes));
}
}
|
Javascript
function maxEnvelopes(envelopes) {
let N = envelopes.length;
if (N === 0) return N;
envelopes.sort((a, b) => {
if (a[0] === b[0]) {
return b[1] - a[1];
} else {
return a[0] - b[0];
}
});
let dp = [];
for (let i = 0; i < N; i++) {
let iter = dp.findIndex(x => x >= envelopes[i][1]);
if (iter === -1) {
dp.push(envelopes[i][1]);
} else if (envelopes[i][1] < dp[iter]) {
dp[iter] = envelopes[i][1];
}
}
return dp.length;
}
let envelopes = [[4, 3], [5, 3], [5, 6], [1, 2]];
console.log(maxEnvelopes(envelopes));
|
Time Complexity: O(N*log(N))
Auxiliary Space: O(N)