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

【Swift 算法实战】城市天际线问题解法

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

网罗开发 (小红书、快手、视频号同名)

  大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等方向。在移动端开发、鸿蒙开发、物联网、嵌入式、云原生、开源等领域有深厚造诣。

图书作者:《ESP32-C3 物联网工程开发实战》
图书作者:《SwiftUI 入门,进阶与实战》
超级个体:COC上海社区主理人
特约讲师:大学讲师,谷歌亚马逊分享嘉宾
科技博主:极星会首批签约作者

文章目录

    • 摘要
    • 描述
    • 题解答案
    • 题解代码分析
      • 步骤解析
      • Swift 代码实现
    • 示例测试及结果
      • 示例 1:
      • 示例 2:
    • 时间复杂度与空间复杂度
    • 总结
    • 参考资料

摘要

城市天际线问题要求根据给定的建筑物位置和高度,计算出从远处看这些建筑物形成的天际线轮廓。每个建筑物都可以用一个三元组 [lefti, righti, heighti] 表示,分别表示建筑物的左边界、右边界和高度。本文将介绍如何使用 Swift 高效地计算天际线,解题过程中会用到优先队列(最大堆)来动态维护当前最大高度,从而生成天际线。

描述

城市的 天际线 是从远处观看该城市中所有建筑物形成的轮廓的外部轮廓。给你所有建筑物的位置和高度,请返回 由这些建筑物形成的 天际线

每个建筑物的几何信息由数组 buildings 表示,其中三元组 buildings[i] = [lefti, righti, heighti] 表示:

  • lefti 是第 i 座建筑物左边缘的 x 坐标。
  • righti 是第 i 座建筑物右边缘的 x 坐标。
  • heighti 是第 i 座建筑物的高度。

你可以假设所有的建筑都是完美的长方形,在高度为 0 的绝对平坦的表面上。

天际线 应该表示为由 “关键点” 组成的列表,格式 [[x1,y1],[x2,y2],...] ,并按 x 坐标 进行 排序关键点是水平线段的左端点。列表中最后一个点是最右侧建筑物的终点,y 坐标始终为 0 ,仅用于标记天际线的终点。此外,任何两个相邻建筑物之间的地面都应被视为天际线轮廓的一部分。

注意: 输出天际线中不得有连续的相同高度的水平线。例如 [...[2 3], [4 5], [7 5], [11 5], [12 7]...] 是不正确的答案;三条高度为 5 的线应该在最终输出中合并为一个:[...[2 3], [4 5], [12 7], ...]

示例 1:

image.png

输入: buildings = [[2,9,10],[3,7,15],[5,12,12],[15,20,10],[19,24,8]]
输出: [[2,10],[3,15],[7,12],[12,0],[15,10],[20,8],[24,0]]
解释:
图 A 显示输入的所有建筑物的位置和高度,
图 B 显示由这些建筑物形成的天际线。图 B 中的红点表示输出列表中的关键点。

示例 2:

输入: buildings = [[0,2,3],[2,5,3]]
输出: [[0,3],[5,0]]

提示:

  • 1 <= buildings.length <= 104
  • 0 <= lefti < righti <= 231 - 1
  • 1 <= heighti <= 231 - 1
  • buildingslefti 非递减排序

题解答案

天际线问题是一个典型的扫描线问题,我们可以通过以下步骤来解决:

  1. 事件建模:首先,将每个建筑物的左端点和右端点视为事件。每个左端点可以看作是一个建筑物的起始位置,需要记录该建筑物的高度;右端点则表示建筑物结束,需要移除该建筑物。

  2. 优先队列(最大堆):利用优先队列(最大堆)来动态维护当前活跃的建筑物的高度。每当遇到左端点时,将建筑物的高度加入堆中;当遇到右端点时,将建筑物的高度从堆中移除。

  3. 生成关键点:通过扫描事件点,我们根据当前堆的最大高度来确定天际线的高度。每当堆的最大值发生变化时,记录下新的关键点。

题解代码分析

步骤解析

  1. 事件构建:将每个建筑物的左端点和右端点作为事件,分别表示建筑物的开始和结束。对于每个事件,我们需要记录其横坐标、事件类型(左端点或右端点)和高度。

  2. 优先队列:使用最大堆来维护当前的建筑物高度,堆的根节点即为当前活跃建筑物的最大高度。

  3. 遍历并生成结果:按横坐标排序所有事件,遍历事件时,动态维护堆,生成天际线的关键点。

Swift 代码实现

import Foundationfunc getSkyline(_ buildings: [[Int]]) -> [[Int]] {var events = [(x: Int, h: Int, type: Int)]()for building in buildings {let (left, right, height) = (building[0], building[1], building[2])events.append((x: left, h: height, type: 1))  // 左端点事件events.append((x: right, h: height, type: -1)) // 右端点事件}// 按照横坐标排序,横坐标相同的事件按类型排序(左端点优先)events.sort { $0.x < $1.x || ($0.x == $1.x && $0.type > $1.type) }var result = [[Int]]()var maxHeap = [(h: Int, count: Int)]() // (高度, 数量),maxHeap 以高度为优先级,模拟最大堆var heightToCount = [Int: Int]() // 高度到数量的映射for event in events {let (x, h, type) = eventif type == 1 { // 左端点heightToCount[h, default: 0] += 1} else { // 右端点heightToCount[h, default: 0] -= 1}// 更新堆var currentHeight = 0for (key, value) in heightToCount {if value > 0 {currentHeight = max(currentHeight, key)}}if result.isEmpty || result.last![1] != currentHeight {result.append([x, currentHeight])}}return result
}

示例测试及结果

示例 1:

let buildings1 = [[2,9,10], [3,7,15], [5,12,12], [15,20,10], [19,24,8]]
print(getSkyline(buildings1)) 
// 输出: [[2, 10], [3, 15], [7, 12], [12, 0], [15, 10], [20, 8], [24, 0]]

示例 2:

let buildings2 = [[0, 2, 3], [2, 5, 3]]
print(getSkyline(buildings2))
// 输出: [[0, 3], [5, 0]]

时间复杂度与空间复杂度

  • 时间复杂度O(n log n)
    排序事件需要 O(n log n) 时间,堆操作也需要 O(log n) 时间,整体复杂度为 O(n log n),其中 n 是建筑物的数量。

  • 空间复杂度O(n)
    存储事件和堆需要 O(n) 的空间,n 为建筑物的数量。

总结

通过扫描线算法并结合最大堆数据结构,我们可以高效地计算出由多个建筑物形成的城市天际线。对于每个建筑物的左端点和右端点事件,我们利用最大堆来维护当前最大高度,并根据高度变化生成关键点。最终我们得到了天际线的正确轮廓。

这种算法不仅能高效地处理较大规模的输入数据,还能保证输出的正确性。随着建筑物数量和坐标范围的增大,这种解法的优势更加突出。

参考资料

  • LeetCode 题目解答:Skyline Problem
  • Swift 官方文档
  • 扫描线算法

相关文章:

【Swift 算法实战】城市天际线问题解法

网罗开发 &#xff08;小红书、快手、视频号同名&#xff09; 大家好&#xff0c;我是 展菲&#xff0c;目前在上市企业从事人工智能项目研发管理工作&#xff0c;平时热衷于分享各种编程领域的软硬技能知识以及前沿技术&#xff0c;包括iOS、前端、Harmony OS、Java、Python等…...

易错点abc

在同一个输入流上重复创建Scanner实例可能会导致一些问题&#xff0c;包括但不限于输入流的混乱。尤其是在处理标准输入&#xff08;System.in&#xff09;时&#xff0c;重复创建Scanner对象通常不是最佳实践&#xff0c;因为这可能导致某些输入数据丢失或者顺序出错。 为什么…...

C++ 正则表达式分组捕获入门指南

在 C 中&#xff0c;正则表达式&#xff08;regex&#xff09;是一种用于匹配字符串模式的强大工具。正则表达式不仅能帮助你查找符合特定模式的字符&#xff0c;还能捕获匹配的子字符串&#xff08;即分组捕获&#xff09;。这篇文章将介绍 C 正则表达式中的分组捕获机制&…...

AI人工智能机器学习之降维和数据压缩

1、概要 本篇学习AI人工智能机器学习之降维和数据压缩&#xff0c;以主成分分析&#xff08;PCA, Principal Component Analysis&#xff09;为例&#xff0c;从代码层面讲述机器学习中的降维和数据压缩。 2、降维和数据压缩 - 简介 在机器学习和数据分析中&#xff0c;降维&…...

17 款电脑压缩工具详解及下载指南(2025 年最新版)

在数字时代,文件压缩是日常工作与生活中不可或缺的操作。无论是视频剪辑师压缩视频以便上传,还是普通用户节省存储空间,一款优质的压缩软件都能极大提升效率。本文将详细介绍 17 款热门电脑压缩软件,涵盖它们的特点、下载地址及适用场景,助你找到最适合自己的工具。 一、…...

DeepSeek开源周Day5压轴登场:3FS与Smallpond,能否终结AI数据瓶颈之争?

2025年2月28日&#xff0c;DeepSeek开源周迎来了第五天&#xff0c;也是本次活动的收官之日。自2月24日启动以来&#xff0c;DeepSeek团队以每天一个开源项目的节奏&#xff0c;陆续向全球开发者展示了他们在人工智能基础设施领域的最新成果。今天&#xff0c;他们发布了Fire-F…...

ROS2软件调用架构和机制解析:Publisher创建

术语 DDS (Data Distribution Service): 用于实时系统的数据分发服务标准&#xff0c;是ROS 2底层通信的基础RMW (ROS Middleware): ROS中间件接口&#xff0c;提供与具体DDS实现无关的抽象APIQoS (Quality of Service): 服务质量策略&#xff0c;控制通信的可靠性、历史记录、…...

【落羽的落羽 C++】C++入门基础·其之一

文章目录 一、C简介1. C的发展历史2. C参考文档 二、namespace命名空间1. C语言的一个缺陷2. namespace3. 命名空间的使用3.1 命名空间成员访问3.2 using展开 一、C简介 1. C的发展历史 C起源于1979年的贝尔实验室&#xff0c;Bjarne Stroustrup&#xff08;本贾尼博士&#…...

docker使用代理的简单配置

1准备代理服务器 准备代理服务器&#xff0c;例如192.168.120.168:52209 配置docker.service文件 查看service文件的位置 systemctl status docker 编辑service文件 vim /usr/lib/systemd/system/docker.service 添加代理配置 ... [Service] Environment"HTTP_PROXY…...

每日一题-设计食物评分系统,哈希表的有效使用

本题出自LeetCode2353.设计食物评分系统&#xff0c;连着一星期都是设计类的题目哈 题目 设计一个支持下述操作的食物评分系统&#xff1a; 修改 系统中列出的某种食物的评分。返回系统中某一类烹饪方式下评分最高的食物。 实现 FoodRatings 类&#xff1a; FoodRatings(Strin…...

大模型应用:多轮对话(prompt工程)

概述 在与大型语言模型&#xff08;如ChatGPT&#xff09;交互的过程中&#xff0c;我们常常体验到与智能助手进行连贯多轮对话的便利性。那么&#xff0c;当我们开启一个新的聊天时&#xff0c;系统是如何管理聊天上下文的呢&#xff1f; 一、初始上下文的建立 1. 创建新会…...

WSDM24-因果推荐|因果去偏的可解释推荐系统

1 动机 可解释推荐系统&#xff08;ERS&#xff09;通过提供透明的推荐解释&#xff0c;提高用户信任度和系统的说服力&#xff0c;如下图所示&#xff0c;然而&#xff1a; 1&#xff1a;现有工作主要关注推荐算法的去偏&#xff08;流行度偏差&#xff09;&#xff0c;但未显…...

VScode在Windows11中配置MSVC

因为MSVC编译器在vs当中&#xff0c;所以我们首先要安装vs的一部分组件。如果只是需要MSVC的话&#xff0c;工作负荷一个都不需要勾选&#xff0c;在单个组件里面搜索MSVC和windows11 SDK&#xff0c;其中一个是编译器&#xff0c;一个是头文件然后右下角安装即可。搜索Develop…...

数据库基础二(数据库安装配置)

打开MySQL官网进行安装包的下载 https://www.mysql.com/ 接着找到适用于windows的版本 下载版本 直接点击下载即可 接下来对应的内容分别是&#xff1a; 1&#xff1a;安装所有 MySQL 数据库需要的产品&#xff1b; 2&#xff1a;仅使用 MySQL 数据库的服务器&#xff1b; 3&a…...

cuda-12.4.0 devel docker 中源码安装 OpenAI triton

1&#xff0c;准备 docker 容器 下载docker image: $ sudo docker pull nvidia/cuda:12.6.2-devel-ubuntu20.04 创建容器&#xff1a; sudo docker run --gpus all -it --name cuda_LHL_01 -v /home/hongleili/ex_triton/tmp1:/root/ex_triton/tmp1 nvidia/cuda:12.6…...

doris: Hive Catalog

通过连接 Hive Metastore&#xff0c;或者兼容 Hive Metatore 的元数据服务&#xff0c;Doris 可以自动获取 Hive 的库表信息&#xff0c;并进行数据查询。 除了 Hive 外&#xff0c;很多其他系统也会使用 Hive Metastore 存储元数据。所以通过 Hive Catalog&#xff0c;我们不…...

【LeetCode】131.分割回文串

目录 题目描述输入输出示例及数据范围思路C 实现 题目描述 这道题目来自 LeetCode 131. 分割回文串。 题目描述如下&#xff1a; 给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是 回文串 。返回 s 所有可能的分割方案。 输入输出示例及数据…...

JeeWMS graphReportController.do SQL注入漏洞复现(CVE-2025-0392)

免责申明: 本文所描述的漏洞及其复现步骤仅供网络安全研究与教育目的使用。任何人不得将本文提供的信息用于非法目的或未经授权的系统测试。作者不对任何由于使用本文信息而导致的直接或间接损害承担责任。如涉及侵权,请及时与我们联系,我们将尽快处理并删除相关内容。 0x0…...

基于Python+django+mysql旅游数据爬虫采集可视化分析推荐系统

2024旅游推荐系统爬虫可视化&#xff08;协同过滤算法&#xff09; 基于Pythondjangomysql旅游数据爬虫采集可视化分析推荐系统 有文档说明 部署文档 视频讲解 ✅️基于用户的协同过滤推荐算法 卖价就是标价~ 项目技术栈 Python语言、Django框架、MySQL数据库、requests网络爬虫…...

我的工作经历

主要说一下毕业工作大半年了一些心得与想法。 首先是因为本科不好的原因&#xff0c;单2硕士找了一个国企&#xff08;其实应该说是央企&#xff09;。也幸好找的是央企&#xff0c;后续工作基本上没有强度&#xff0c;不然后期神经衰弱抑郁症家里乱七八糟催婚的事情能把人逼疯…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式

今天是关于AI如何在教学中增强学生的学习体验&#xff0c;我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育&#xff0c;这并非炒作&#xff0c;而是已经发生的巨大变革。教育机构和教育者不能忽视它&#xff0c;试图简单地禁止学生使…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解

在 C/C 编程的编译和链接过程中&#xff0c;附加包含目录、附加库目录和附加依赖项是三个至关重要的设置&#xff0c;它们相互配合&#xff0c;确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中&#xff0c;这些概念容易让人混淆&#xff0c;但深入理解它们的作用和联…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...

CSS | transition 和 transform的用处和区别

省流总结&#xff1a; transform用于变换/变形&#xff0c;transition是动画控制器 transform 用来对元素进行变形&#xff0c;常见的操作如下&#xff0c;它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...

【JVM】Java虚拟机(二)——垃圾回收

目录 一、如何判断对象可以回收 &#xff08;一&#xff09;引用计数法 &#xff08;二&#xff09;可达性分析算法 二、垃圾回收算法 &#xff08;一&#xff09;标记清除 &#xff08;二&#xff09;标记整理 &#xff08;三&#xff09;复制 &#xff08;四&#xff…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)

前言&#xff1a; 双亲委派机制对于面试这块来说非常重要&#xff0c;在实际开发中也是经常遇见需要打破双亲委派的需求&#xff0c;今天我们一起来探索一下什么是双亲委派机制&#xff0c;在此之前我们先介绍一下类的加载器。 目录 ​编辑 前言&#xff1a; 类加载器 1. …...

【FTP】ftp文件传输会丢包吗?批量几百个文件传输,有一些文件没有传输完整,如何解决?

FTP&#xff08;File Transfer Protocol&#xff09;本身是一个基于 TCP 的协议&#xff0c;理论上不会丢包。但 FTP 文件传输过程中仍可能出现文件不完整、丢失或损坏的情况&#xff0c;主要原因包括&#xff1a; ✅ 一、FTP传输可能“丢包”或文件不完整的原因 原因描述网络…...

Linux入门课的思维导图

耗时两周&#xff0c;终于把慕课网上的Linux的基础入门课实操、总结完了&#xff01; 第一次以Blog的形式做学习记录&#xff0c;过程很有意思&#xff0c;但也很耗时。 课程时长5h&#xff0c;涉及到很多专有名词&#xff0c;要去逐个查找&#xff0c;以前接触过的概念因为时…...