当前位置: 首页 > news >正文

Swift 实战:用最长递增子序列算法解“俄罗斯套娃信封”问题(LeetCode 354)

在这里插入图片描述
在这里插入图片描述

文章目录

    • 摘要
    • 描述
    • 解决方案
    • 解析问题和答案
      • 细节解释
    • 示例和结果
    • 时间复杂度
    • 空间复杂度
    • 总结

摘要

这道题表面是“套娃游戏”,实际上是一个二维排序 + 最长递增子序列(LIS)的经典组合题。我们要在一堆信封中,找出能一层套一层的最大数量。本文会从零开始分析题目、拆解解法、实现一个 Swift 可运行 Demo,并结合实际场景聊聊为什么这种思路很常见。看完之后,你不仅能秒杀这题,还能举一反三,处理各种二维排序 + LIS 的场景。

描述

题目给我们一组信封,每个信封用 [w, h] 表示宽度和高度。要求在不旋转信封的前提下,找出能层层套入的最大信封数量。

规则:

  • 信封 A 可以套进信封 B,当且仅当 wA < wB && hA < hB
  • 不能旋转信封(也就是不能交换宽高)。
  • 要求返回最多能套多少层。

示例 1:

输入: [[5,4],[6,4],[6,7],[2,3]]
输出: 3
解释: [2,3] -> [5,4] -> [6,7]

示例 2:

输入: [[1,1],[1,1],[1,1]]
输出: 1

数据范围:

  • 1 <= envelopes.count <= 10^5
  • 1 <= wi, hi <= 10^5

解决方案

这题的高效解法是:

  1. 排序处理宽度

    • width 升序排序。
    • 如果宽度相同,按 height 降序排序(防止宽相等但高递增的情况被误当成可套娃)。
  2. 在高度序列上找 LIS

    • 排序后,问题变成了在“高度”序列中找最长严格递增子序列。
    • 高度序列的 LIS 长度,就是最大套娃数量。
  3. 二分优化 LIS

    • 常规 LIS 是 O(n²),但这里 n 可达 10^5,需要用二分法把复杂度降到 O(n log n)。

这个套路其实在很多二维比较的题目里都适用,比如“安排会议”、“选拔球员”等等。

解析问题和答案

下面是完整可运行的 Swift 代码。为了方便跑样例,我在同一个文件里加了测试函数。

import Foundationstruct RussianDollEnvelopes {func maxEnvelopes(_ envelopes: [[Int]]) -> Int {guard !envelopes.isEmpty else { return 0 }// 1. 按宽升序,高降序排序let sortedEnvelopes = envelopes.sorted { a, b inif a[0] == b[0] {return a[1] > b[1] // 宽相等时,高度降序} else {return a[0] < b[0] // 否则宽升序}}// 2. 提取高度序列let heights = sortedEnvelopes.map { $0[1] }// 3. 在 heights 上找 LIS(严格递增)return lengthOfLIS(heights)}// 二分优化的 LISprivate func lengthOfLIS(_ nums: [Int]) -> Int {var dp = [Int]()for num in nums {// 找到第一个 >= num 的位置var left = 0var right = dp.countwhile left < right {let mid = (left + right) / 2if dp[mid] < num {left = mid + 1} else {right = mid}}if left < dp.count {dp[left] = num} else {dp.append(num)}}return dp.count}
}

细节解释

  1. 为什么宽相等时要按高降序?
    假设有 [3,3][3,4],如果按高升序,LIS 会错误地认为 [3,3] -> [3,4] 可套娃,但宽相等所以不行。降序能破坏这种错误递增。

  2. 二分法找位置
    dp 数组是“当前长度的递增子序列的最小尾值”,二分查找能 O(log n) 定位替换位置。

  3. 时间复杂度

    • 排序 O(n log n)
    • LIS O(n log n)
    • 总体 O(n log n),n = envelopes.count
  4. 空间复杂度

    • 排序需要 O(log n) 栈空间
    • dp 最多长度为 n,O(n) 空间

示例和结果

func testRussianDollEnvelopes() {let solver = RussianDollEnvelopes()let case1 = [[5,4],[6,4],[6,7],[2,3]]print("Case 1 Result:", solver.maxEnvelopes(case1)) // 3let case2 = [[1,1],[1,1],[1,1]]print("Case 2 Result:", solver.maxEnvelopes(case2)) // 1let case3 = [[4,5],[4,6],[6,7],[2,3],[1,1]]print("Case 3 Result:", solver.maxEnvelopes(case3)) // 4let case4 = [[2,100],[3,200],[4,300],[5,500],[5,400],[5,250],[6,370],[6,360],[7,380]]print("Case 4 Result:", solver.maxEnvelopes(case4)) // 5
}testRussianDollEnvelopes()

输出示例:

Case 1 Result: 3
Case 2 Result: 1
Case 3 Result: 4
Case 4 Result: 5

这几组用例覆盖了常规、重复、边界和复杂排序的情况。

时间复杂度

  • 排序:O(n log n)
  • LIS(二分法):O(n log n)
  • 总体:O(n log n)
    可以轻松处理 n=10^5 级别的数据。

空间复杂度

  • 额外空间主要是存放 dp 数组和排序临时空间:O(n)。
  • 没有额外递归开销,空间使用很稳定。

总结

这题其实是“二维 LIS”的经典模板:

  1. 先排序破坏非法情况:宽升序 + 宽相等高降序。
  2. 在一维上做 LIS:把问题降维到 O(n log n) 的 LIS。
  3. 实现细节很关键:高降序是防错的核心,二分法是提速的关键。

现实中,这种“两个维度都要递增”的需求很常见,比如信封套娃、球员身高体重选拔、会议时间安排等。掌握这个套路,你可以应对各种类似的二维排序 + LIS 问题。

http://www.lryc.cn/news/622026.html

相关文章:

  • Effective C++ 条款42:了解 typename 的双重含义
  • 旅游管理实训室:旅游教育实践育人的关键支撑
  • spring中异步任务注解@Async和@scheduled的使用
  • 5G赋能井下“毛细血管”:巴拉素煤矿零散排水点智能监控系统
  • 基于阿里云音频识别模型的网页语音识别系统实现
  • Spring WebFlux 性能优化实践指南
  • 近日算法备案事项:九月批复审即将启动/赶11月批最后安全启动时间已过
  • week1-[顺序结构]跑道
  • YAML 中定义 List 的几种方式
  • WEB安全--Java安全--Servlet内存马
  • 第十四节:物理引擎集成:Cannon.js入门
  • Linux之高可用集群实战(二)
  • 机器学习 - Kaggle项目实践(4)Toxic Comment Classification Challenge 垃圾评论分类问题
  • 嵌入式第二十九课!!!回收子进程资源空间函数与exec函数
  • 大模型——如何让 AI 绘图的中文呈现更稳定和准确
  • Spring 条件注解与 SPI 机制(深度解析)
  • LeetCode 面试经典 150_数组/字符串_最长公共前缀(20_14_C++_简单)(暴力破解)(求交集)
  • Docker 实战:情感分析系统-容器化部署全流程(sa-logic、sa-webapp、sa-frontend )
  • Highcharts Dashboards | 打造企业级数据仪表板:从图表到数据驾驶舱
  • CUDA 编程笔记:GPU 硬件资源
  • 敏捷数据开发实践:基于 Amazon Q Developer + Remote MCP 构建本地与云端 Amazon Redshift 交互体系
  • mysql-条件查询案例
  • C++从入门到实战(十九)C++ vector容器及其常用接口
  • dockerfile自定义镜像,乌班图版
  • 【开源大模型和闭源大模型分别有哪些?两者的对比?部署私有化模型的必要性有哪些?】
  • 解决zabbix图片中文乱码
  • Spring Boot 拦截器详解
  • HarmonyOS Camera Kit 全解析:从基础拍摄到跨设备协同的实战指南
  • 开源 Arkts 鸿蒙应用 开发(十六)自定义绘图控件--波形图
  • 成品电池综合测试仪:一站式评估性能与安全