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++
// C++ program for the above approach #include <bits/stdc++.h> using namespace std; Â
// Function that returns the maximum // number of envelopes that can be // inserted into another envelopes int maxEnvelopes(vector<vector< int > > envelopes) {     // Number of envelopes     int N = envelopes.size(); Â
    if (N == 0)         return N; Â
    // Sort the envelopes in     // non-decreasing order     sort(envelopes.begin(),         envelopes.end()); Â
    // Initialize dp[] array     int dp[N]; Â
    // To store the result     int max_envelope = 1; Â
    dp[0] = 1; Â
    // Loop through the array     for ( int i = 1; i < N; ++i) {         dp[i] = 1; Â
        // Find envelopes count for         // each envelope         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;         } Â
        // Store maximum envelopes count         max_envelope = max(max_envelope,                         dp[i]);     } Â
    // Return the result     return max_envelope; } Â
// Driver Code int main() {     // Given the envelopes     vector<vector< int > > envelopes         = { { 4, 3 }, { 5, 3 }, { 5, 6 }, { 1, 2 } }; Â
    // Function Call     cout << maxEnvelopes(envelopes); Â
    return 0; } |
Java
// Java program for the above approach import java.util.*; import java.lang.*; Â
class GFG{      // Function that returns the maximum // number of envelopes that can be // inserted into another envelopes static int maxEnvelopes( int [][] envelopes) {          // Number of envelopes     int N = envelopes.length;          if (N == 0 )         return N;          // Sort the envelopes in     // non-decreasing order     Arrays.sort(envelopes,                (a, b) -> (a[ 0 ] != b[ 0 ]) ?                           a[ 0 ] - b[ 0 ] :                           a[ 1 ] - b[ 1 ]);                                // Initialize dp[] array     int [] dp = new int [N];          // To store the result     int max_envelope = 1 ;          dp[ 0 ] = 1 ;          // Loop through the array     for ( int i = 1 ; i < N; ++i)     {         dp[i] = 1 ;                  // Find envelopes count for         // each envelope         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 ;         }                  // Store maximum envelopes count         max_envelope = Math.max(max_envelope, dp[i]);     }          // Return the result     return max_envelope; } Â
// Driver Code public static void main (String[] args) {          // Given the envelopes     int [][] envelopes = { { 4 , 3 }, { 5 , 3 },                           { 5 , 6 }, { 1 , 2 } };          // Function call     System.out.println(maxEnvelopes(envelopes)); } } Â
// This code is contributed by offbeat |
Python3
# Python3 program for the above approach Â
# Function that returns the maximum # number of envelopes that can be # inserted into another envelopes def maxEnvelopes(envelopes): Â
    # Number of envelopes     N = len (envelopes) Â
    if (N = = 0 ):         return N Â
    # Sort the envelopes in     # non-decreasing order     envelopes = sorted (envelopes) Â
    # Initialize dp[] array     dp = [ 0 ] * N Â
    # To store the result     max_envelope = 1 Â
    dp[ 0 ] = 1 Â
    # Loop through the array     for i in range ( 1 , N):         dp[i] = 1 Â
        # Find envelopes count for         # each envelope         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 Â
        # Store maximum envelopes count         max_envelope = max (max_envelope, dp[i]) Â
    # Return the result     return max_envelope Â
# Driver Code if __name__ = = '__main__' : Â
    # Given the envelopes     envelopes = [ [ 4 , 3 ], [ 5 , 3 ],                 [ 5 , 6 ], [ 1 , 2 ] ] Â
    # Function Call     print (maxEnvelopes(envelopes)) Â
# This code is contributed by Mohit Kumar |
C#
// C# program to implement above approach using System; using System.Collections; using System.Collections.Generic; Â
class GFG {     // Function that returns the maximum     // number of envelopes that can be     // inserted into another envelopes     static int maxEnvelopes( int [][] envelopes)     {                  // Number of envelopes         int N = envelopes.Length;                  if (N == 0){             return N;         }                  // Sort the envelopes in         // non-decreasing order         Array.Sort(envelopes, new comp());                                      // Initialize dp[] array         int [] dp = new int [N];                  // To store the result         int max_envelope = 1;                  dp[0] = 1;                  // Loop through the array         for ( int i = 1 ; i < N ; ++i)         {             dp[i] = 1;                          // Find envelopes count for             // each envelope             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;                 }             }                          // Store maximum envelopes count             max_envelope = Math.Max(max_envelope, dp[i]);         }                  // Return the result         return max_envelope;     } Â
    // Driver code     public static void Main( string [] args){ Â
        // Given the envelopes         int [][] envelopes = new int [][]{             new int []{ 4, 3 },             new int []{ 5, 3 },             new int []{ 5, 6 },             new int []{ 1, 2 }         };                  // Function call         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]; Â Â Â Â } } Â
// This code is contributed by entertain2022. |
Javascript
<script> Â
// JavaScript program for the above approach Â
// Function that returns the maximum // number of envelopes that can be // inserted into another envelopes function maxEnvelopes(envelopes) {     // Number of envelopes     var N = envelopes.length; Â
    if (N == 0)         return N; Â
    // Sort the envelopes in     // non-decreasing order     envelopes.sort(); Â
    // Initialize dp[] array     var dp = Array(N); Â
    // To store the result     var max_envelope = 1; Â
    dp[0] = 1; Â
    // Loop through the array     for ( var i = 1; i < N; ++i) {         dp[i] = 1; Â
        // Find envelopes count for         // each envelope         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;         } Â
        // Store maximum envelopes count         max_envelope = Math.max(max_envelope,                         dp[i]);     } Â
    // Return the result     return max_envelope; } Â
// Driver Code Â
// Given the envelopes var envelopes     = [ [ 4, 3 ], [ 5, 3 ], [ 5, 6 ], [ 1, 2 ] ];      // Function Call document.write( maxEnvelopes(envelopes)); Â
Â
</script> |
3
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++
// C++ program for the above approach #include <bits/stdc++.h> using namespace std; Â
// Function that returns the maximum // number of envelopes that can be // inserted into another envelopes int maxEnvelopes(vector<vector< int > >& envelopes) {     // Number of envelopes     int N = envelopes.size(); Â
    if (N == 0)         return N; Â
    // Sort the envelopes in increasing     // order of width and decreasing order     // of height is width is same     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]);         }); Â
    // To store the longest increasing     // sequence of height     vector< int > dp; Â
    // Finding LIS of the heights     // of the envelopes     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 the result     return dp.size(); } Â
// Driver Code int main() {     // Given the envelopes     vector<vector< int > > envelopes         = { { 4, 3 }, { 5, 3 }, { 5, 6 }, { 1, 2 } }; Â
    // Function Call     cout << maxEnvelopes(envelopes);     return 0; } |
Java
// Java program for the above approach import java.io.*; import java.util.*; import java.util.Arrays; import java.util.Collections; Â
class GFG{ Â
  // Function that returns the maximum   // number of envelopes that can be   // inserted into another envelopes   static int maxEnvelopes( int [][] envelopes)   { Â
    // Number of envelopes     int N = envelopes.length; Â
    if (N == 0 )       return N; Â
    // Sort the envelopes in increasing     // order of width and decreasing order     // of height is width is same     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 ];;       }     }); Â
    // To store the longest increasing     // sequence of height     ArrayList<Integer> dp = new ArrayList<Integer>(); Â
    // Finding LIS of the heights     // of the envelopes     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 the result     return dp.size();   } Â
  // Driver Code   public static void main (String[] args)   { Â
    // Given the envelopes     int [][] envelopes = { { 4 , 3 }, { 5 , 3 }, { 5 , 6 }, { 1 , 2 } }; Â
    // Function Call     System.out.println(maxEnvelopes(envelopes));   } } Â
// This code is contributed by Aman Kumar |
Python3
# Python program for the above approach from bisect import bisect_left as lower_bound Â
# Function that returns the maximum # number of envelopes that can be # inserted into another envelopes def maxEnvelopes(envelopes):     # Number of envelopes     N = len (envelopes)          if (N = = 0 ):         return N          # Sort the envelopes in increasing     # order of width and decreasing order     # of height is width is same     envelopes.sort()          # To store the longest increasing     # sequence of height     dp = []          # Finding LIS of the heights     # of the envelopes     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 the result     return len (dp) Â
# Driver Code Â
# Given the envelopes envelopes = [[ 4 , 3 ], [ 5 , 3 ], [ 5 , 6 ], [ 1 , 2 ]] Â
# Function Call print (maxEnvelopes(envelopes)) Â
# This code is contributed by Pushpesh Raj |
C#
using System; using System.Linq; using System.Collections.Generic; Â
class GFG {      // Function that returns the maximum   // number of envelopes that can be   // inserted into another envelopes   static int maxEnvelopes( int [][] envelopes)   {          // Number of envelopes     int N = envelopes.Length; Â
    if (N == 0)       return N; Â
    // Sort the envelopes in increasing     // order of width and decreasing order     // of height is width is same     Array.Sort(envelopes, (a, b) = > a[0] - b[0]); Â
    // To store the longest increasing     // sequence of height     List< int > dp = new List< int >(); Â
    // Finding LIS of the heights     // of the envelopes     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 the result     return dp.Count;   } Â
  // Driver Code   static void Main( string [] args)   {     // Given the envelopes     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 }; Â
    // Function Call     Console.WriteLine(maxEnvelopes(envelopes));   } } Â
// This code is contributed by lokeshpotta20. |
Javascript
// JavaScript program for the above approach Â
// Function that returns the maximum // number of envelopes that can be // inserted into another envelopes function maxEnvelopes(envelopes) {   // Number of envelopes   let N = envelopes.length; Â
  if (N === 0) return N; Â
  // Sort the envelopes in increasing   // order of width and decreasing order   // of height is width is same   envelopes.sort((a, b) => {     if (a[0] === b[0]) {       return b[1] - a[1];     } else {       return a[0] - b[0];     }   }); Â
  // To store the longest increasing   // sequence of height   let dp = []; Â
  // Finding LIS of the heights   // of the envelopes   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 the result   return dp.length; } Â
// Driver Code let envelopes = [[4, 3], [5, 3], [5, 6], [1, 2]]; Â
// Function Call console.log(maxEnvelopes(envelopes)); // this contributed by devendra |
3
Time Complexity: O(N*log(N))
Auxiliary Space: O(N)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!