Axis­ Aligned 
Rectangles (Google 面试题, 2016网易游戏校招笔试)

Describe 
an
 algorithm 
that 
takes 
an 
unsorted 
array 
of 
axis‐aligned 
rectangles 
and
 returns 
any 
pair 
of 
rectangles 
that
 overlaps,
 if 
there
 is 
such
 a 
pair.
 
Axis‐aligned
 means
 that
 all 
the
 rectangle
 sides
 are 
either 
parallel
 or
 perpendicular 
to
 the
 x‐
 and
 y‐axis. 

You
 can
 assume 
that
 each
 rectangle
 object
 has
 two 
variables
in
 it: 
the 
x‐y
 coordinates 
of 
the
 upper‐left 
corner 
and 
the 
bottom‐right 
corner.

Good
 Answer: 
Create
 a 
sorted 
array 
of
 the
 x
 coordinates 
of 
the
 left
 and
 right
 edges 
of
 the 
rectangles. 

Then, 
use 
a
 "scanline" 
to
 move
 from
 left 
to 
right 
through
 the
 rectangles. 

Keep 
a
 binary
 search
 tree 
containing 
the
 y 
coordinates 
of 
the
 top
 and
 bottom
 edges 
of 
the
 rectangles
 that
 overlap 
the 
scanline. 

For 
each
 element
 of 
the
 array,
 check
 whether 
it 
is 
a
 left 
or 
right
 edge.
 
If 
it 
is 
a 
right
 edge, 
remove
 the
 corresponding
 top
 and 
bottom
 edges 
from 
the 
BST.

 If 
it 
is 
a
left 
edge,
 search
 the
 BST
 for 
rectangles
 that
 overlap 
the
 current
 rectangle; 
if 
there
 is 
one,
return 
the
 overlap.

 Then,
 add 
the
y
 coordinates 
of
 the
 top
 and
 bottom
edges
 of 
the 
rectangle
 to 
the 
BST.

 The
 search
 takes 
O(n
log
n) 
time,
 since 
it 
takes 
O(n
log
n) 
time
 to
 sort
 the
 rectangles
 and
 each
 of 
the
 2n 
iteration s
takes 
O(log
n)
 time.

C++ Sample Code (Find all pairs of rectangles that overlap): 

 1 #include <iostream>
 2 #include <vector>
 3 #include <map>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 struct rect {
 8     int _x1, _x2, _y1, _y2;
 9     rect(int x1, int x2, int y1, int y2) :
10         _x1(x1), _x2(x2), _y1(y1), _y2(y2) {}
11 };
12 
13 struct xedge {
14     int _x;
15     int _is_left;
16     int _i_rect;
17     xedge(int x, int is_left, int i_rect) :
18         _x(x), _is_left(is_left), _i_rect(i_rect) {}
19 };
20 
21 struct yedge {
22     int _y;
23     int _is_top;
24     int _i_rect;
25     yedge(int y, int is_top, int i_rect) :
26         _y(y), _is_top(is_top), _i_rect(i_rect) {} 
27 };
28 
29 int main() {
30     vector<rect> rcts; // vector that stores rectangles
31     vector<xedge> xes; // left and right edges of the rectangles
32     int x1, x2, y1, y2;
33     int i = 0;
34     while (cin >> x1 >> x2 >> y1 >> y2) {
35         rcts.push_back(rect(x1, x2, y1, y2));
36         xes.push_back(xedge(x1, 1, i));
37         xes.push_back(xedge(x2, 0, i));
38         i++;
39     }
40 
41     // sort left and right rectangles according to their x-coordinates
42     sort(xes.begin(), xes.end(), 
43         [](const xedge& e1, const xedge& e2) {
44             if (e1._x != e2._x) return e1._x < e2._x;
45             else if (e1._is_left != e2._is_left) 
46                 return e1._is_left > e2._is_left;
47             else return e1._i_rect < e2._i_rect;
48         });
49 
50     // a binary search tree for top and bottom edges that overlap the "scanline"
51     multimap<int, yedge> edge_map;
52     for (auto& xe : xes) { // xe : "scanline"
53         if (!xe._is_left) { 
54             auto range = edge_map.equal_range(rcts[xe._i_rect]._y1); 
55             for (auto iter = range.first; iter != range.second; ++iter) {
56                 if (iter->second._i_rect == xe._i_rect) {
57                     edge_map.erase(iter);
58                     break;
59                 }
60             }
61             range = edge_map.equal_range(rcts[xe._i_rect]._y2); 
62             for (auto iter = range.first; iter != range.second; ++iter) {
63                 if (iter->second._i_rect == xe._i_rect) {
64                     edge_map.erase(iter);
65                     break;
66                 }
67             }
68         } else {
69             int y1 = rcts[xe._i_rect]._y1;
70             int y2 = rcts[xe._i_rect]._y2;
71             auto iter1 = edge_map.lower_bound(y1);
72             auto iter2 = edge_map.upper_bound(y2);
73             for (auto iter = iter1; iter != iter2; ++iter) {
74                 cout << xe._i_rect << " " << iter->second._i_rect << endl;
75             }
76             edge_map.insert(make_pair(y1, yedge(y1, 0, xe._i_rect)));
77             edge_map.insert(make_pair(y2, yedge(y2, 1, xe._i_rect)));
78         }
79     }
80 
81     return 0;
82 }

 

原文地址:https://www.cnblogs.com/william-cheung/p/4603359.html