华为OD机考双机位C卷 - 书籍叠放 (Java & Python & JS & GO & C++ & C)

书籍叠放

2026华为OD机试双机位C卷 - 华为OD上机考试双机位C卷

华为OD机试双机位C卷真题目录点击查看: 【全网首发】2026华为OD机位C卷 机考真题题库含考点说明以及在线OJ(OD上机考试双机位C卷)

题目描述

书籍的长、宽都是整数对应(l,w)。如果书A的长宽度都比B长宽大时,则允许将B排列放在A上面。

现在有一组规格的书籍,书籍叠放时要求书籍不能做旋转,请计算最多能有多少个规格书籍能叠放在一起。

输入描述

输入:books = [[20,16],[15,11],[10,10],[9,10]]

说明:总共4本书籍,第一本长度为20宽度为16;第二本书长度为15宽度为11,依次类推,最后一本书长度为9宽度为10.

输出描述

输出:3

说明: 最多3个规格的书籍可以叠放到一起, 从下到上依次为: [20,16],[15,11],[10,10]

示例1

输入

[[20,16],[15,11],[10,10],[9,10]]

输出

3

说明

解题思路

题目分析

题目要求我们计算一组书籍最多能叠放多少本。
叠放的条件是:上面书籍的长和宽必须严格小于下面书籍的长和宽。
也就是说,如果书 A 放在书 B 上面,必须满足:A.length < B.lengthA.width < B.width
这是一个典型的二维偏序问题,可以转化为最长递增子序列 (LIS) 问题来求解。

解题策略

为了简化问题,我们可以先固定一个维度,然后再在另一个维度上求解 LIS。

  1. 排序
    首先,我们将所有书籍按照长度 (length) 从小到大进行排序。
    这样一来,对于排在后面的书 B 和前面的书 A,B 的长度一定大于等于 A 的长度。

    • 处理长度相同的情况:如果两本书长度相同,比如 [10, 5][10, 8],如果不做特殊处理,直接按宽度求 LIS,可能会出现选取了 [10, 5] 然后选取 [10, 8] 的情况(因为 $5 < 8$)。
    • 但实际上,长度相同的书是不能相互叠放的。
    • 技巧:当长度相同时,我们按照宽度 (width) 从大到小排序。
    • 原因:假设排序后是 [10, 8], [10, 5]。我们在求宽度的最长递增子序列时,由于 $8 > 5$,这两个数不可能同时被选入一个严格递增的序列中。这就保证了长度相同的书不会被同时选中。
  2. 转化为 LIS 问题
    经过上述排序后,对于任意选取的两本书 $i$ 和 $j$($i < j$):

    • 必然满足 books[i].length <= books[j].length
    • 如果 books[i].length == books[j].length,则根据排序规则,books[i].width >= books[j].width,此时书 $j$ 不能放在书 $i$ 上面(因为需要严格小于,且这里我们是寻找能叠放的序列,实际上是找一个子序列使得长宽都单调递增)。
    • 注意:原题描述是从下往上叠,还是从上往下叠?
      • 题目说“如果书A的长宽度都比B长宽大时,则允许将B排列放在A上面”。即大的在下面,小的在上面。
      • 我们可以反过来思考,找一个序列,使得从上到下长和宽都严格递增。
    • 根据我们的排序(长升序,长同宽降序),我们只需要在宽度数组中寻找最长严格递增子序列 (LIS)
    • 为什么?
      • 假设我们在宽度数组中找到了一个递增子序列 $w_{i_1}, w_{i_2}, \dots, w_{i_k}$,其中 indices $i_1 < i_2 < \dots < i_k$。
      • 对于任意相邻的两个元素 $p$ and $q$ ($p$ 在 $q$ 前面),有 $w_p < w_q$。
      • 由于 $p$ 在 $q$ 前面,根据主排序规则:$L_p \le L_q$。
      • 如果 $L_p == L_q$,根据次排序规则(宽降序),必有 $w_p \ge w_q$。但这与 $w_p < w_q$ 矛盾。
      • 因此,必须有 $L_p < L_q$。
      • 结论:只要在排序后的数组中找到宽度的严格递增子序列,其对应的长度也一定是严格递增的。
  3. 计算 LIS

    • 可以使用动态规划,时间复杂度 $O(N^2)$。
    • 更优的方法是使用贪心 + 二分查找,时间复杂度 $O(N \log N)$。
    • 维护一个 tails 数组,tails[i] 表示长度为 i+1 的递增子序列的最小尾部元素。
    • 遍历每个宽度 $w$:
      • 如果 $w$ 大于 tails 的末尾元素,直接追加。
      • 否则,用二分查找在 tails 中找到第一个大于等于 $w$ 的元素并替换之。

复杂度分析

  • 时间复杂度:排序 $O(N \log N)$,计算 LIS $O(N \log N)$。总复杂度 $O(N \log N)$。
  • 空间复杂度:需要存储书籍和 LIS 辅助数组,为 $O(N)$。
posted @ 2026-03-08 22:32  华为od算法大师  阅读(4)  评论(0)    收藏  举报