令 V[m] 为具有最大 y 坐标的顶点。
要考虑的最简单的情况是m=1
,何时V[2].y < V[1].y > v[n].y
。由于排除这种情况使后续推理更简单,我们假设对这种情况进行了初始检查。
考虑一条以 V[i] 为原点的边 E[i],其中1<i<=n
. 鉴于所有 x 和 y 坐标都不同的约束,E[i] 必须位于 4 个平面象限之一中:
鉴于我们已经排除了 的情况m=i=1
,对于位于象限 I、II 或 IV 中的 E[i],它必须是 的情况m>i
。如果 E[i] 位于象限 III 中,则为 ,如果或m=i
,则为真。V[i].y > V[i-1].y
m<i
我们可以将此推理用作二分搜索的基础,在每次迭代中我们执行:
if E[i] lies in Quadrant III
if V[i].y > V[i-1].y then m=i
else consider left half
else
consider right half
下面是一些 Java 代码来说明:
static Point maxY(Point[] v)
{
// check for max at origin
if(v[1].y < v[0].y && v[v.length-1].y < v[0].y)
{
return v[0];
}
int left = 0;
int right = v.length-1;
Point maxY = null;
while(left <= right)
{
int mid = left + (right-left)/2;
if(v[(mid+1)%v.length].y < v[mid].y && v[(mid+1)%v.length].x < v[mid].x)
{
// Quadrant III
if(v[mid].y > v[mid-1].y)
{
maxY = v[mid];
break;
}
right = mid - 1;
}
else
{
left = mid + 1;
}
}
return maxY;
}
还有一些简单的测试用例:
public static void main(String[] args)
{
Point[][] tests = {
{new Point(0, 10), new Point(10, 0), new Point(9, 5)},
{new Point(0, 0), new Point(9, 5), new Point(10, 10)},
{new Point(0, 0), new Point(10, 10), new Point(5, 8)},
{new Point(0, 5), new Point(9, 0), new Point(10, 10)},
{new Point(0, 5), new Point(6,0), new Point(10, 6), new Point(5,10)}};
for(Point[] coords : tests)
System.out.println(maxY(coords) + " : " + Arrays.toString(coords));
}
输出:
(0, 10) : [(0, 10), (10, 0), (9, 5)]
(10, 10) : [(0, 0), (9, 5), (10, 10)]
(10, 10) : [(0, 0), (10, 10), (5, 8)]
(10, 10) : [(0, 5), (9, 0), (10, 10)]
(5, 10) : [(0, 5), (6, 0), (10, 6), (5, 10)]