218. The Skyline Problem

原创 2018年04月15日 21:03:38

A city's skyline is the outer contour of the silhouette formed by all the buildings in that city when viewed from a distance. Now suppose you are given the locations and height of all the buildings as shown on a cityscape photo (Figure A), write a program to output the skyline formed by these buildings collectively (Figure B).

The geometric information of each building is represented by a triplet of integers [Li, Ri, Hi], where Li and Ri are the x coordinates of the left and right edge of the ith building, respectively, and Hi is its height. It is guaranteed that 0 ≤ Li, Ri ≤ INT_MAX, 0 < Hi ≤ INT_MAX, and Ri - Li > 0. You may assume all buildings are perfect rectangles grounded on an absolutely flat surface at height 0.

For instance, the dimensions of all buildings in Figure A are recorded as: [ [2 9 10], [3 7 15], [5 12 12], [15 20 10], [19 24 8] ] .

The output is a list of "key points" (red dots in Figure B) in the format of [ [x1,y1], [x2, y2], [x3, y3], ... ] that uniquely defines a skyline. A key point is the left endpoint of a horizontal line segment. Note that the last key point, where the rightmost building ends, is merely used to mark the termination of the skyline, and always has zero height. Also, the ground in between any two adjacent buildings should be considered part of the skyline contour.

For instance, the skyline in Figure B should be represented as:[ [2 10], [3 15], [7 12], [12 0], [15 10], [20 8], [24, 0] ].

Notes:

  • The number of buildings in any input list is guaranteed to be in the range [0, 10000].
  • The input list is already sorted in ascending order by the left x position Li.
  • The output list must be sorted by the x position.
  • There must be no consecutive horizontal lines of equal height in the output skyline. For instance, [...[2 3], [4 5], [7 5], [11 5], [12 7]...] is not acceptable; the three lines of height 5 should be merged into one in the final output as such: [...[2 3], [4 5], [12 7], ...]

题目的意思大概如下:

有一堆建筑物,它们都是标准的长方形,给我们的数据是vector<vector<int>> A(A.size(), B(3)),A中存储着所有的建筑的信息,A[i][0]是建筑物的左上顶点的横坐标,A[i][1]是右上顶点的横坐标,A[i][2]是建筑物的高度,建筑物不透光,所以当它们重叠排在一起时,我们只能看到它们作为整体的边,现在要求计算这些作为边的线,用关键点表达这些边,关键点是我们能看到的建筑物部分的左上角的点。

对于这道题,显然按照我们自然思维是不太好做的,自然思想是将所有的图形画出来,然后描边,但是用程序实现较为麻烦。

建筑物都是长方形,可以用边来表示,甚至因为这些长方形的底边在同一条线上,所以这些长方形可以用左上顶点和右上顶点标识。

那么什么时候才会出现key point呢,有以下的情况:

1. 一个建筑物特别高大,它的左顶点没有被挡住,那么它的左顶点就是一个key point

2. 例如途中的红色建筑物和绿色建筑物,由于绿色建筑物的左顶点被红色建筑物挡住了,所以此时绿色建筑物上存在的key point点就是绿色建筑物和红色建筑物右边的交点

我们要得到上图中的key point点,自然想到的是,先是蓝色建筑物的左顶点,然后红色建筑物比蓝色建筑物高大,红色建筑物的左顶点也是一个key point,然后是绿色建筑物的左顶点,但是绿色建筑物的左顶点被红色建筑物挡住了,所以忽略掉这个点,接下来是红色建筑物的右顶点,遍历到这个点说明红色建筑物的这段已经走完了,红色建筑物的右边和绿色建筑物顶此时的相交的点也是一个key point,这个key point A的高度信息来源于绿色建筑物,而前面走过的点只有绿色建筑物的左顶点具备这个信息,这说明,我们在遍历这些点时,要存储着这些点的高度信息,那么为什么key point A的高度信息是绿色建筑物的而不是蓝色建筑物的呢,毕竟此时的蓝色建筑物还没走完呐,这是因为蓝色建筑物的高度没有绿色建筑物的高,如果蓝色建筑物的高度大于绿色建筑物的高度,那么key point A的高度就是蓝色建筑物的高度。以上的分析说明,我们在写代码的时候要记录还未走完的建筑物的高度信息,而某个建筑物一旦走完(遇到建筑物的右顶点),则将其高度信息移出。

再观察一下,可以发现所有的key point的高度都是未走完建筑物的最高高度,例如绿色建筑物上的key point的高度信息来自于当前还未走完的建筑物集合{蓝色,绿色建筑物}的最高高度,黄色建筑物上的key point也是如此。

于是产生了一种想法,从左到右遍历左右的顶点,并这些顶点的高度信息存入到一个堆或者一个优先队列中,保证可以取到当前未走完建筑物的最大高度,如果遇到左顶点,判断该顶点的高度是否大于堆或优先队列的最大值,如果是,则说明遇到了一个新的key point,否则说明这个点被挡住了,如果遇到右顶点,则将对应的左顶点的高度信息取出,(该右顶点的横坐标,优先队列的peek)则又是一个新的key point

然后C++STL中的堆和优先队列是不能删除指定元素的,set可以,但是set中不予许duplicates,所以采用multiset这种很有意思的数据结构。

代码如下:

vector<pair<int, int>> getSkyline(vector<vector<int>>& buildings)
{
	if(bulidings.size() == 0)return {};
	multiset<pair<int, int>> bulidings_roof;
	for(int i = 0; i < bulidings.size(); i++)
	{
		bulidings_roof.insert({bulidings[i][0], -1 * bulidings[i][2]});
		bulidings_roof.insert({bulidings[i][1], bulidings[i][2]});
	}
	multiset<int> heights;
	vector<pair<int, int>> result;
	heights.insert(0);
	int pre = 0;
	for(auto point : bulidings_roof)
	{
		if(point.second < 0)heights.insert(-1 * point.second);
		else heights.erase(heights.find(point.second));
		int peek = *heights.rbegin();//the current highest roof that haven't finished
		if(peek != pre)
		{
			result.push_back({point.first, peek});
			pre = peek;
		}
	}
	return result;
}

时间复杂度:O(2n),n代表的是长方形的个数

leetcode 218: The Skyline Problem

leetcode 218: The Skyline Problem java python c++
  • xudli
  • xudli
  • 2015-06-03 18:10:47
  • 4678

LeetCode218:The Skyline Problem

A city's skyline is the outer contour of the silhouette formed by all the buildings in that city whe...
  • u012501459
  • u012501459
  • 2015-08-04 11:09:06
  • 1893

[leetcode] 218. The Skyline Problem 解题报告

题目链接: https://leetcode.com/problems/the-skyline-problem/ A city's skyline is the outer contour of ...
  • qq508618087
  • qq508618087
  • 2016-05-04 09:41:29
  • 1748

Leetcode 218 The Skyline Problem

1. 问题描述   Notes: The number of buildings in any input list is guaranteed to be in the range [0, 100...
  • Jeanphorn
  • Jeanphorn
  • 2015-06-25 16:44:14
  • 7635

LeetCode218. The Skyline Problem分治法

题意:轮廓问题,不好描述。首先怎么分: 不停对半分 停止条件1:为空时,直接返回空 停止条件2:大小为1时,直接返回左上角点和右下角点。 那么怎么合并? 维护两个变量:l,r l为左半部分当前位置,r...
  • wmdshhz0404
  • wmdshhz0404
  • 2016-10-12 12:18:59
  • 456

LeetCode 218. The Skyline Problem--Divide and Conquer(分治法)

题目链接 218. The Skyline Problem A city's skyline is the outer contour of the silhouette formed by al...
  • monkey_rose
  • monkey_rose
  • 2017-09-13 21:45:32
  • 196

[LeetCode]--218. The Skyline Problem

[LeetCode]--218. The Skyline Problem
  • beijingbuaaer
  • beijingbuaaer
  • 2016-08-14 21:15:11
  • 119

Leetcode 218. The Skyline Problem

原题:A city's skyline is the outer contour of the silhouette formed by all the buildings in that city ...
  • muche001
  • muche001
  • 2018-02-28 15:21:24
  • 11

leetcode 218. The Skyline Problem

A city's skyline is the outer contour of the silhouette formed by all the buildings in that city whe...
  • liqinzhe11
  • liqinzhe11
  • 2017-10-09 16:28:44
  • 94

218. The Skyline Problem (最大堆)

题意: 给你一堆建筑的左右边界和高度,让你求其映射到坐标系后,所有有效的拐点(详情看原题) 思路: 用线性表维护每个建筑的左右边界坐标,按横坐标升序排序后遍历,遍历时用最大堆维护某横坐标上存在的...
  • exp1ore
  • exp1ore
  • 2017-11-24 20:50:29
  • 55
收藏助手
不良信息举报
您举报文章:218. The Skyline Problem
举报原因:
原因补充:

(最多只允许输入30个字)