📌  相关文章
📜  可以放入其他较大信封中的最大信封数

📅  最后修改于: 2021-05-13 22:26:18             🧑  作者: Mango

给定N个信封,即{W,H}对,其中W为宽度, H为高度。当且仅当一个信封的宽度和高度都大于另一个信封的宽度和高度时,一个信封才能装入另一个信封。查找可以放入另一个信封的最大信封数,依此类推。不允许旋转信封。

例子:

天真的方法:此问题类似于动态规划的最长增长子序列问题。想法是按不降序对信封进行分类,并针对每个信封检查可放入该信封的信封数量。请按照以下步骤解决问题:

  • 按宽度和高度的降序对数组进行排序。
  • 初始化一个dp []数组,其中dp [i]存储可以将信封[i]作为最大信封放入其中的信封数。
  • 对于每个信封[i],循环遍历小于其自身的信封,并检查较小信封的宽度和高度是否严格小于信封[i]的宽度和高度如果小于,则可以将较小的信封放入信封[i]中。
  • dp []数组的最大值给出了可以放入彼此的最大信封数。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
  
// Function that returns the maximum
// number of envelopes that can be
// inserted into another envelopes
int maxEnvelopes(vector > 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 > 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 for the above approach
#include 
using namespace std;
  
// Function that returns the maximum
// number of envelopes that can be
// inserted into another envelopes
int maxEnvelopes(vector >& 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& a, vector& 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 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 > envelopes
        = { { 4, 3 }, { 5, 3 }, { 5, 6 }, { 1, 2 } };
  
    // Function Call
    cout << maxEnvelopes(envelopes);
    return 0;
}


输出:
3

时间复杂度: O(N 2 )
辅助空间: O(N)

高效方法:要优化天真的方法,其思想是使用二进制搜索的概念 和最长的递增子序列。如果宽度相同,则按照宽度的递增顺序和高度的递减顺序对信封进行排序,这减少了寻找最长的信封高度递增顺序的问题。这种方法适用于宽度已经按升序排序的情况,并且只有最大的高度递增序列才足以找到最大数量的信封。本文讨论了在N×log(N)方法中找到最长增长序列的有效方法。

下面是上述方法的实现:

C++

// C++ program for the above approach
#include 
using namespace std;
  
// Function that returns the maximum
// number of envelopes that can be
// inserted into another envelopes
int maxEnvelopes(vector >& 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& a, vector& 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 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 > envelopes
        = { { 4, 3 }, { 5, 3 }, { 5, 6 }, { 1, 2 } };
  
    // Function Call
    cout << maxEnvelopes(envelopes);
    return 0;
}
输出:
3

时间复杂度: O( N * log(N) )
辅助空间: O(N)