题目:
平面上有一些点,每个点的坐标可用(x,y)表示。请找出所有的极点。
对于平面上的两个点:A(x1,y1) 和 B(x2,y2),如果x1>x2,且y1>y2,则点A支配点B。极点是不被其他点支配的点。
思路:
暴力法的时间复杂度是O(n2)。本题利用分治法可以使时间复杂度降到NlogN
。具体步骤:
- 首先对数组排序,使所有点在x轴上从小到大排列
- 把数组分为左右两部分,分别求极点
- 对2步骤的两个结果合并,不过要先过滤左边部分有可能被右边极点支配的点。
代码:
#include <vector>
using namespace std;
class MaximumPoint {
static bool compareTwoPoint(vector<int> point1, vector<int> point2) {
return point1[0] < point2[0];
}
public:
vector<vector<int>> findMaximumPoint(vector<vector<int>>& arr, int left, int right) {
if (left > right) {
return {{}};
}
if (left == right) {
return {arr[left]};
}
sort(arr.begin(), arr.begin()+(right - left), compareTwoPoint);
int mid = left + (right - left)/2;
vector<vector<int>> leftR = findMaximumPoint(arr,left,mid);
vector<vector<int>> rightR = findMaximumPoint(arr, mid + 1, right);
//找出rightR里 x最小的极点
vector<int> minPoint = rightR.front();
for(int i = 1;i < rightR.size();i++) {
if (minPoint[0] > rightR[i][0]) {
minPoint = rightR[i];
}
}
//如果leftR里,有点y < minPoin[1],则排除
for(int i = 0;i < leftR.size();i++) {
if (leftR[i][1] < minPoint[1]) {
leftR.erase(leftR.begin()+i);
i--;
}
}
//合并 leftR和rightR
rightR.insert(rightR.end(), leftR.begin(), leftR.end());
return rightR;
}
};