记录 Line Sweep 的算法实现
“218. The Skyline Problem”
func getSkyline(buildings [][]int) (ret [][]int) {
arr := make([]*[2]int, 0, len(buildings)*2) // (坐标, 高度)
for _, b := range buildings {
// 用负数表示开始高度,以便排序时开始比结束更靠前
arr = append(arr, &[2]int{b[0],-b[2]}, &[2]int{b[1],b[2]})
}
sort.Slice(arr, func(a, b int) bool {
if arr[a][0] == arr[b][0] {
return arr[a][1] < arr[b][1] // 再按高度
}
return arr[a][0] < arr[b][0] // 先按坐标
})
h := new(myHeap)
maxHeight := 0
for _, cur := range arr {
if cur[1] < 0 {
if -cur[1] > maxHeight {
maxHeight = -cur[1]
ret = append(ret, []int{cur[0], maxHeight})
}
heap.Push(h, &[2]int{cur[0], -cur[1]})
} else {
for i := 0; i < h.Len(); i++ {
if (*h)[i][1] == cur[1] {
heap.Remove(h, i)
break
}
}
if h.Len() > 0 {
if (*h)[0][1] == maxHeight {
continue
} else if (*h)[0][1] < maxHeight {
maxHeight = (*h)[0][1]
}
} else {
maxHeight = 0
}
ret = append(ret, []int{cur[0], maxHeight})
}
}
return ret
}
type myHeap []*[2]int // (坐标, 高度)
func (p *myHeap) Len() int { return len(*p) }
func (p *myHeap) Less(a, b int) bool {
return (*p)[a][1] > (*p)[b][1]
}
func (p *myHeap) Swap(a, b int) { (*p)[a], (*p)[b] = (*p)[b], (*p)[a] }
func (p *myHeap) Push(x interface{}) { (*p) = append((*p), x.(*[2]int)) }
func (p *myHeap) Pop() interface{} {
tmp := (*p)[len(*p)-1]
(*p) = (*p)[:len(*p)-1]
return tmp
}
“253. Meeting Rooms II”
func minMeetingRooms(intervals [][]int) (ret int) {
n := len(intervals)
sli := make([]int, n*2)
for i, j := 0, 0; i < n; i, j = i+1, j+2 {
sli[j] = intervals[i][0]<<1 + 1
sli[j+1] = intervals[i][1]<<1
}
sort.Ints(sli)
num := 0
for _, i := range sli {
if i & 1 == 0 {
num--
} else {
num++
}
if num > ret {
ret = num
}
}
return ret
}
“850. Rectangle Area II”
int rectangleArea(vector<vector<int>>& rectangles) {
if (rectangles.empty() || rectangles[0].empty()) return 0;
const int N = rectangles.size(), OPEN = 0, CLOSE = 1;
vector<vector<int>> events(N * 2, vector<int>(4));
for (int i = 0; i < N; ++i) {
events[2 * i] = {rectangles[i][1], OPEN, rectangles[i][0], rectangles[i][2]};
events[2 * i + 1] = {rectangles[i][3], CLOSE, rectangles[i][0], rectangles[i][2]};
}
sort(events.begin(), events.end());
vector<vector<int>> active;
int cur_y = events[0][0];
long ans = 0;
for (auto &e : events) {
int y = e[0], type = e[1], x1 = e[2], x2 = e[3];
long query = 0;
int cur = -1;
for (auto &a : active) {
cur = max(cur, a[0]);
query += max(a[1] - cur, 0);
cur = max(cur, a[1]);
}
ans += query * (y - cur_y);
if (type == OPEN) {
active.push_back({x1, x2});
sort(active.begin(), active.end());
} else {
for (int i = 0; i < active.size(); ++i) {
if (active[i][0] == x1 && active[i][1] == x2) {
active.erase(active.begin() + i);
break;
}
}
}
cur_y = y;
}
ans %= 1000000007;
return ans;
}
“986. Interval List Intersections”
// version 1
func intervalIntersection(firstList [][]int, secondList [][]int) (ret [][]int) {
type changePoint struct {
pos int
action bool // false end; true start
}
allActions := make([]*changePoint, 0, len(firstList)*2 + len(secondList)*2)
for _, v := range firstList {
allActions = append(allActions, &changePoint{v[0], true}, &changePoint{v[1], false})
}
for _, v := range secondList {
allActions = append(allActions, &changePoint{v[0], true}, &changePoint{v[1], false})
}
sort.Slice(allActions, func(a, b int) bool {
if allActions[a].pos == allActions[b].pos {
return allActions[a].action
}
return allActions[a].pos < allActions[b].pos
})
for i, count, lastStart := 0, 0, 0; i < len(allActions); i++ {
if allActions[i].action {
count++
lastStart = allActions[i].pos
} else {
if count > 1 {
ret = append(ret, []int{lastStart, allActions[i].pos})
}
count--
}
}
return ret
}
// version 2
func intervalIntersection(firstList [][]int, secondList [][]int) (ret [][]int) {
for i, j := 0, 0; i < len(firstList) && j < len(secondList); {
low, high := max(firstList[i][0], secondList[j][0]), min(firstList[i][1], secondList[j][1])
if low <= high {
ret = append(ret, []int{low, high})
}
if firstList[i][1] < secondList[j][1] {
i++
} else {
j++
}
}
return ret
}
“1288. Remove Covered Intervals”
func removeCoveredIntervals(intervals [][]int) (count int) {
sort.Slice(intervals, func(a, b int) bool {
if intervals[a][0] == intervals[b][0] {
return intervals[a][1] > intervals[b][1]
}
return intervals[a][0] < intervals[b][0]
})
for i, end := 0, math.MinInt32; i < len(intervals); i++ {
if intervals[i][1] > end {
count++
end = intervals[i][1]
}
}
return count
}