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

📅  最后修改于: 2021-09-17 06:42:56             🧑  作者: 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


Javascript


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)

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程