LeetCode 218. 天际线问题 【Python 扫描线法】

本文介绍了如何使用Python解决LeetCode的天际线问题,通过扫描线法来确定关键点,并针对算法进行优化,包括避免无用检测和使用堆数据结构提高效率。
摘要由CSDN通过智能技术生成

本文发布且更新于个人博客:https://www.xerrors.fun/leetcode-the-skyline-problem/

1. 题目

城市的天际线是从远处观看该城市中所有建筑物形成的轮廓的外部轮廓。现在,假设您获得了城市风光照片(图A)上显示的所有建筑物的位置和高度,请编写一个程序以输出由这些建筑物形成的天际线(图B)。

链接:https://leetcode-cn.com/problems/the-skyline-problem

例如,图A中所有建筑物的尺寸记录为:[ [2 9 10], [3 7 15], [5 12 12], [15 20 10], [19 24 8] ]

输出是以[ [x1,y1], [x2, y2], [x3, y3], ... ]格式的“关键点”(图B中的红点)的列表,它们唯一地定义了天际线。关键点是水平线段的左端点。请注意,最右侧建筑物的最后一个关键点仅用于标记天际线的终点,并始终为零高度。此外,任何两个相邻建筑物之间的地面都应被视为天际线轮廓的一部分。

例如,图B中的天际线应该表示为:[ [2 10], [3 15], [7 12], [12 0], [15 10], [20 8], [24, 0] ]

说明:

  • 任何输入列表中的建筑物数量保证在 [0, 10000] 范围内。
  • 输入列表已经按左 x 坐标 Li 进行升序排列。
  • 输出列表必须按 x 位排序。
  • 输出天际线中不得有连续的相同高度的水平线。例如 [...[2 3], [4 5], [7 5], [11 5], [12 7]...] 是不正确的答案;三条高度为 5 的线应该在最终输出中合并为一个:[...[2 3], [4 5], [12 7], ...]

2. 解题思路

开始的思路

思路其实很容易想到,就像是一条流水线一样,拿着一根垂直线沿着X轴方向移动,每一个时刻都判断当前建筑的最高的那个建筑的高度,跟上一个时刻的最高的高度相比,如果不一样那么就代表这个点是一个关键点。

同时,把当前时刻的建筑保存在一个数组里面,方法是需要在每一个时刻都检查是否有新的建筑进入数组,之后需要检查是否有建筑结束了。

但是恐怖就在于,超时了,这里引用一位网友的话:

自行优化

这时候来分析一下这个用例的特点:这个建筑特别大,特别高,只有一个。所以就是说我们在每一个时刻都要判断是都有新的建筑以及是否有建筑被删除,然后在这个例子里面,这些判断都是徒劳的,只有一个建筑。所以优化的方向就是不要对这些无用点进行检测,所以采用的办法就是把原本的扫描点替换成有意义的点,也就是建筑物的边缘点:

points = []
for k in buildings:
	if k[0] not in points:
		points.append(k[0])
	if k[1] not in points:
		points.append(k[1])
points.sort()

但是,新的问题就出现了,[[1,2,1],[1,2,2],[1,2,3]] 这个例子的特点是三个建筑物重叠但是高度不一样,按理说应该不是问题,但是出现了一个意想不到的错误,那么是遍历删除的时候出现的错误;当我们的扫描线到达点 2 的时候,这三个建筑都应当从数组中删除,但是:

for build in q:
    if build[1] <= points[i]:
        q
你好!对于LeetCode上的问题994.腐烂的橘子,你可以使用Python来解决。下面是一个示例代码: ```python from collections import deque def orangesRotting(grid): # 记录网格的行数和列数 row, col = len(grid), len(grid[0]) # 定义四个方向:上、下、左、右 directions = [(-1, 0), (1, 0), (0, -1), (0, 1)] # 使用队列来保存腐烂的橘子的位置 queue = deque() # 记录新鲜橘子的数量 fresh_count = 0 # 遍历整个网格,初始化队列和新鲜橘子的数量 for i in range(row): for j in range(col): if grid[i][j] == 2: # 腐烂的橘子 queue.append((i, j)) elif grid[i][j] == 1: # 新鲜橘子 fresh_count += 1 # 如果新鲜橘子的数量为0,直接返回0 if fresh_count == 0: return 0 # 初始化分钟数 minutes = 0 # 开始进行BFS,直到队列为空 while queue: # 记录当前分钟数下,队列中的元素数量 size = len(queue) # 遍历当前分钟数下的所有腐烂的橘子 for _ in range(size): x, y = queue.popleft() # 遍历四个方向 for dx, dy in directions: nx, ny = x + dx, y + dy # 判断新位置是否在网格内,并且是新鲜橘子 if 0 <= nx < row and 0 <= ny < col and grid[nx][ny] == 1: # 将新鲜橘子变为腐烂状态 grid[nx][ny] = 2 # 将新鲜橘子的位置加入队列 queue.append((nx, ny)) # 新鲜橘子的数量减1 fresh_count -= 1 # 如果当前分钟数下,没有新鲜橘子了,结束循环 if fresh_count == 0: break # 每遍历完一层,分钟数加1 minutes += 1 # 如果最后还有新鲜橘子,返回-1,否则返回分钟数 return -1 if fresh_count > 0 else minutes ``` 你可以将给定的网格作为参数传递给`orangesRotting`函数来测试它。请注意,该代码使用了BFS算法来遍历橘子,并计算腐烂的分钟数。希望能对你有所帮助!如果有任何疑问,请随时问我。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值