当前位置: 面试刷题>> 俄罗斯套娃信封 (经典算法题500道)


题目描述补充

俄罗斯套娃信封问题(Russian Doll Envelopes Problem)

给定一组信封,每个信封都有其宽度和高度的尺寸,问最多能使用多少个信封,使得在放置下一个信封时,这个信封的宽度和高度都必须严格小于前一个信封的宽度和高度。目的是要找出最长的信封序列(套娃序列),使得每个信封都能被下一个信封完全包裹。

示例

假设有以下信封尺寸(以宽度和高度为一对表示):

[[5,4],[6,4],[6,7],[2,3]]

最长套娃序列的长度是 3,即 [2,3] -> [5,4] -> [6,7]

解题思路

这个问题可以转化为最长递增子序列(LIS)问题,但需要考虑两个维度(宽度和高度)。由于LIS算法本身只考虑一维递增,我们需要通过某种方式将二维问题转化为一维。常见的方法是先将信封按照宽度进行排序(如果宽度相同,则按高度降序排序),然后只对高度这一维使用LIS算法。

PHP 示例代码

function maxEnvelopes($envelopes) {
    // 按宽度升序排序,宽度相同则按高度降序排序
    usort($envelopes, function($a, $b) {
        if ($a[0] == $b[0]) {
            return $b[1] - $a[1];
        }
        return $a[0] - $b[0];
    });

    $heights = array_column($envelopes, 1);
    return lengthOfLIS($heights);
}

function lengthOfLIS($nums) {
    $n = count($nums);
    if ($n <= 1) return $n;

    $dp = array_fill(0, $n, 1);
    $maxLength = 1;

    for ($i = 1; $i < $n; $i++) {
        for ($j = 0; $j < $i; $j++) {
            if ($nums[$i] > $nums[$j]) {
                $dp[$i] = max($dp[$i], $dp[$j] + 1);
            }
        }
        $maxLength = max($maxLength, $dp[$i]);
    }

    return $maxLength;
}

// 示例
$envelopes = [[5,4],[6,4],[6,7],[2,3]];
echo maxEnvelopes($envelopes);  // 输出 3

Python 示例代码

def maxEnvelopes(envelopes):
    # 按宽度升序排序,宽度相同则按高度降序排序
    envelopes.sort(key=lambda x: (x[0], -x[1]))

    heights = [env[1] for env in envelopes]
    return lengthOfLIS(heights)

def lengthOfLIS(nums):
    dp = [1] * len(nums)
    maxLength = 1

    for i in range(1, len(nums)):
        for j in range(i):
            if nums[i] > nums[j]:
                dp[i] = max(dp[i], dp[j] + 1)
        maxLength = max(maxLength, dp[i])

    return maxLength

# 示例
envelopes = [[5,4],[6,4],[6,7],[2,3]]
print(maxEnvelopes(envelopes))  # 输出 3

JavaScript 示例代码

function maxEnvelopes(envelopes) {
    // 按宽度升序排序,宽度相同则按高度降序排序
    envelopes.sort((a, b) => {
        if (a[0] === b[0]) return b[1] - a[1];
        return a[0] - b[0];
    });

    const heights = envelopes.map(env => env[1]);
    return lengthOfLIS(heights);
}

function lengthOfLIS(nums) {
    const dp = new Array(nums.length).fill(1);
    let maxLength = 1;

    for (let i = 1; i < nums.length; i++) {
        for (let j = 0; j < i; j++) {
            if (nums[i] > nums[j]) {
                dp[i] = Math.max(dp[i], dp[j] + 1);
            }
        }
        maxLength = Math.max(maxLength, dp[i]);
    }

    return maxLength;
}

// 示例
const envelopes = [[5,4],[6,4],[6,7],[2,3]];
console.log(maxEnvelopes(envelopes));  // 输出 3

// 码小课网站中有更多相关内容分享给大家学习

以上代码示例均实现了俄罗斯套娃信封问题的解决方案,并展示了如何在PHP、Python和JavaScript中编写。

推荐面试题