LC 218. The Skyline Problem
https://leetcode.com/problems/the-skyline-problem/
这题目大约两种做法:
- 使用区间数树来不断地更新每个区间的高度。这个做法非常直接,但是代码写出来比较长 参考代码
- 另外一种方法类似 LC 1897 Meeting Room III 的方法,将所有building按照X轴排个序,这个序相当于进入视野的顺序,然后不断地更新每个区间的高度。 参考代码
我个人觉得方法2更容易实现,虽然先需要绕点弯子(对X轴进行排序)。此外还有几个小点需要处理:
- 这种方法有可能会得到 [x,x,h] 这样的区间表示,所以需要判断 `ev.x > cur`
- 在最后面离开视野的时候,需要补上0.
- 某些区间是可以进行合并的,比如 [x, y, h2], [y, y2, h2] -> [x, y2, h2]
lintcode 上面也有这道题目,只不过在输出上略微不同而已 参考代码.
另外这题目只能使用Java/C++来写,Python里面是没有现成的TreeSet/TreeMap实现的。
还有就是容器里面的Integer比较相等,必须使用 `x.equals(y)`, 教训啊!
import java.util.*;
class Event implements Comparable<Event> {
int in;
int x;
int h;
int idx;
public Event(int in, int x, int h, int idx) {
this.in = in;
this.x = x;
this.h = h;
this.idx = idx;
}
public int compareTo(Event it) {
return x - it.x;
}
}
class Building implements Comparable<Building> {
int h;
int idx;
public Building(int h, int idx) {
this.h = h;
this.idx = idx;
}
public int compareTo(Building it) {
if (this.h != it.h) {
return this.h - it.h;
}
return this.idx - it.idx;
}
}
class Solution {
public List<List<Integer>> getSkyline(int[][] buildings) {
int n = buildings.length;
List<List<Integer>> ans = new ArrayList<>();
if (n == 0) {
return ans;
}
Event[] events = new Event[2 * n];
for (int i = 0; i < n; i++) {
events[2 * i] = new Event(0, buildings[i][0], buildings[i][2], i);
events[2 * i + 1] = new Event(1, buildings[i][1], buildings[i][2], i);
}
Arrays.sort(events);
TreeSet<Building> ts = new TreeSet<>();
int cur = events[0].x;
for (int i = 0; i < events.length; i++) {
Event ev = events[i];
int h = 0;
if (ts.size() > 0) {
h = ts.last().h;
}
if (ev.in == 0) {
if ((h < ev.h) && (ev.x > cur)) {
ArrayList<Integer> t = new ArrayList();
t.add(cur);
t.add(h);
cur = ev.x;
ans.add(t);
}
ts.add(new Building(ev.h, ev.idx));
} else {
if ((h == ev.h) && (ev.x > cur)) {
ArrayList<Integer> t = new ArrayList();
t.add(cur);
t.add(h);
cur = ev.x;
ans.add(t);
}
ts.remove(new Building(ev.h, ev.idx));
}
}
ArrayList<Integer> t = new ArrayList();
t.add(cur);
t.add(0);
ans.add(t);
List<List<Integer>> res = new ArrayList<>();
for (int i = 0; i < ans.size(); i++) {
int j = res.size();
if ((j > 0) && res.get(j - 1).get(1).equals(ans.get(i).get(1))) {
continue;
}
res.add(ans.get(i));
}
return res;
}
}