这是一个经典的二维“最大点”或“支配关系”问题,下面是完整的解答:
一个点 ( x i , y i ) (x_i, y_i) (xi,yi) 被支配,是指存在另一个点 ( x j , y j ) (x_j, y_j) (xj,yj),满足:
我们要找出 所有不被支配的点,即最大点集合(Maximal Points)。
按 x 坐标降序排序;
从左往右扫描每个点,维护一个变量 max_y_so_far
;
如果当前点的 y 大于 max_y_so_far
,就说明它不是被别人支配的最大点;
更新 max_y_so_far
。
#include
#include
#include
using namespace std;
struct Point {
int x, y;
};
bool compare(const Point& a, const Point& b) {
// 按 x 降序排列;若 x 相同,按 y 升序排列
return a.x > b.x || (a.x == b.x && a.y < b.y);
}
vector<Point> findMaximalPoints(vector<Point>& points) {
sort(points.begin(), points.end(), compare);
vector<Point> result;
int max_y_so_far = INT_MIN;
for (const auto& p : points) {
if (p.y > max_y_so_far) {
result.push_back(p);
max_y_so_far = p.y;
}
}
return result;
}
步骤 | 时间复杂度 |
---|---|
排序 | O ( n log n ) O(n \log n) O(nlogn) |
扫描 | O ( n ) O(n) O(n) |
总计 | O ( n log n ) O(n \log n) O(nlogn) ✅ |
这个“最大点”问题又叫二维天空线问题(Skyline problem),在以下场景中很常见:
产品优选筛选:
房地产分析:
数据库多维查询优化:
投资组合选择:
就业择业建议系统:
{(1,3), (2,2), (3,1), (4,4), (5,0)}
(5, 0)
是不是最大点呢?
是的,在严格按照定义的支配关系下,(5,0) 也确实是最大点,因为:
最大点不一定“好看”或“数值最大”;
它只是“不被别人同时在 x 和 y 上都更优”:
好的!我们现在来扩展到三维空间,即处理点集合 ( x , y , z ) (x, y, z) (x,y,z),并找出所有不被其他点支配的最大点。
在三维中,点 A = ( x 1 , y 1 , z 1 ) A = (x_1, y_1, z_1) A=(x1,y1,z1) 支配点 B = ( x 2 , y 2 , z 2 ) B = (x_2, y_2, z_2) B=(x2,y2,z2),当且仅当:
我们要找出所有不被其他点支配的最大点。
由于三维不再能像二维那样用排序+扫描处理,我们用:
这适合中等规模(例如 n ≤ 1 0 4 n \leq 10^4 n≤104)。
#include
#include
using namespace std;
struct Point3D {
int x, y, z;
void print() const {
cout << "(" << x << ", " << y << ", " << z << ")";
}
};
// 判断 A 是否支配 B
bool dominates(const Point3D& A, const Point3D& B) {
bool strictly_greater = false;
if (A.x < B.x || A.y < B.y || A.z < B.z)
return false;
if (A.x > B.x) strictly_greater = true;
if (A.y > B.y) strictly_greater = true;
if (A.z > B.z) strictly_greater = true;
return strictly_greater;
}
vector<Point3D> findMaximalPoints3D(const vector<Point3D>& points) {
int n = points.size();
vector<bool> is_dominated(n, false);
for (int i = 0; i < n; ++i) {
if (is_dominated[i]) continue;
for (int j = 0; j < n; ++j) {
if (i == j) continue;
if (dominates(points[j], points[i])) {
is_dominated[i] = true;
break;
}
}
}
vector<Point3D> result;
for (int i = 0; i < n; ++i) {
if (!is_dominated[i])
result.push_back(points[i]);
}
return result;
}
int main() {
vector<Point3D> points = {
{1, 2, 3}, {3, 2, 1}, {2, 3, 1}, {4, 4, 4}, {5, 0, 0}, {0, 5, 0}, {0, 0, 5}
};
vector<Point3D> maximal = findMaximalPoints3D(points);
cout << "三维最大点(不被支配的点)有:" << endl;
for (const auto& p : maximal) {
p.print();
cout << endl;
}
return 0;
}
三维最大点(不被支配的点)有:
(4, 4, 4)
(5, 0, 0)
(0, 5, 0)
(0, 0, 5)
这些点都没有在 x、y、z 三维中被其他点“更大等”且至少一维更大的点支配。