假设我有一个名为Point的对象数组 点对象具有x和y值。
为了使它更难,让我们说没有初始边界,这意味着我们想要找到的矩形区域受Point对象的限制。因此,至少有4个Point对象。
所以如果数组只有4个Point对象:Point(0,0),Point(100,0)Point(0,100)和Point(100,100),我们想要返回100 * 100的矩形区域。
这很容易。但是考虑有超过4个Point对象的情况。你如何找到最大的矩形区域?
public int maxArea(Point[] points)
{
int area;
//do algo
return area;
}
编辑:只是通过查看y的最小值和最大值而x不能保证因为我正在寻找没有Point对象的矩形区域。所以最大矩形区域内没有任何东西
答案 0 :(得分:3)
让我首先阐述问题,因为我认为这意味着:
要找到的矩形具有水平(常数y)和垂直(常数x)边界,即没有“旋转”。
矩形在每个边缘的“内部”(“开放”)部分至少有一个点,即不在角落。 (它可能在任何边缘都有多个点,并且也指向其角落。) 这排除了“无限”解,因为所有点都有有限的x,y。 它还排除了我们打算仅通过TopLeft和BottomRight点以及类似结构来定义矩形的情况。
我们寻找满足上述条件的最大面积的矩形。
假设以上是问题的正确(重新)公式,我认为这是一个二维优化问题,可能存在许多“局部”最优。 任何类型的“从某事开始并逐渐改进”的方法只能找到局部最优,但不一定是全局的。
我还没有能够提出比O(N ^ 2)方法更好的方法,粗略地讲 - N次本地优化,其中每个局部优化都是O(N)。 我将使用一些代码片段(部分伪代码或备注)为本地优化的基本部分描绘方法。 其余部分“更多相同”,不应该难以填写。
为了减少措辞而不会变得不准确,从此我将意味着“边缘(一个recctangle)上的一个点”在边缘的“内部”部分而不是在角落处。 同样,通过'矩形',我将指一个“符合条件的”反应角,即满足基本条件的反应角:内部没有点,每个边上至少有一个点。
现在,LOCAL优化由点集中的特定点“定义”,并结合来自{Left,Top,Right,Bottom}的特定“border-type”。 假设我们选择了一个L点和边界类型“Left”;局部最优解决方案被定义为在其左边缘具有L的“最佳”(最大区域)矩形。
我们将构建所有(L,左) - 矩形并跟踪我们在途中找到的最大的那些。
观察:任何(L,左) - 在其右边界上有点R的直角,其顶部边界上必须有一个点T,而在其下边界上必须有一个点B,其中
L.x < T.x < R.x
L.x < B.X < R.X
B.y < L.y < T.y
B.y < R.y < T.Y
现在,我们以L顺序扫描点,从L开始。
一方面:在我们找到R之前,上述条件表明我们必须首先遇到T和B.
另一方面,一旦我们找到了R,所有的点都是y&gt;我们在中间遇到过的,我们现在将受到y最低的那个的约束。同样适用于底线。
N点数{P}, 令index_X []为x排序点的索引数组,使得P [index_X [i]] x&lt; = P [index_X [j]] .x只要i小于j。
此外,让iL成为x排序数组中L的索引:P [index_X [iL]] = L.
在下面的代码片段中(VB语法;使用您使用的任何语言翻译都不会太难),我们首先确定“某些”T(顶部边缘点)和“部分”B(一个底边点)。 然后,我们继续扫描,每当我们找到完成矩形的点R时,我们: (a)如果面积较大,则计算更新最佳面积; (b)用找到的R代替T或B(取决于R是高于L还是低于L),并重复搜索R.
Dim indx As Integer = iL + 1 'first point to consider on the right of L
Dim T As PointF = Nothing
Dim B As PointF = Nothing
' find T,B
While (indx < N AndAlso (T = Nothing OrElse B = Nothing))
Dim Q As PointF = Pts(indx_X(indx))
If (Q.Y > L.Y) Then
' a candidate for T
If (T = Nothing) OrElse (Q.Y < T.Y) Then
T = Q
End If
ElseIf (Q.Y < L.Y) Then
' a candidate for B
If (B = Nothing) OrElse (Q.Y > B.Y) Then
B = Q
End If
Else
Return -1 'Failure for L altogether: Q has exactly the same y-value as L and we didn't find yet both T and B.
End If
indx += 1
End While
If (T = Nothing OrElse B = Nothing) Then
Return -1 'Failure for L: we have exhausted all points on the right without finding both T and B.
End If
' we have "some" T and B, now proceed to find all (L,Left) rectangles
' intialize result (= max area from (L,Left)-rectangles).
Dim result As Double = -1
' the next point to consider
indx += 1
' find successive rectangles, by searching for R, given L (fixed) and T,B (occasionally updated).
While (indx < N)
Dim R As PointF = Pts(indx_X(indx)) 'candidate
If (R.Y = L.Y) Then
' rectangle found, process it.
Dim area As Double = (R.X - L.X) * (T.Y - B.Y)
If area > result Then
result = area
End If
' it all stops here: no further rectangles {L,Left) are possible as they would have this R inside.
Exit While
End If
If (R.Y > L.Y) Then
' a point with y > L.Y:
' if it is above T we can ignore it.
' if is below T, it is the R-bound for the rectangle bounded by L,T,B
If (R.Y < T.Y) Then
' process the rectangle
Dim area As Double = (R.X - L.X) * (T.Y - B.Y)
If area > result Then
result = area
End If
' move on, understanding that for any NEXT rectangle this R must be the upperbound.
T = R
End If
Else 'R.Y < L.Y
' a point with y < L.Y
' if it is below B we can ignore it.
' if it is above B, it is the R-bound for the rectangle bounded by L,T,B
If (R.Y > B.Y) Then
' process the rectangle
Dim area As Double = (R.X - L.X) * (T.Y - B.Y)
If area > result Then
result = area
End If
' move on, understanding that for any NEXT rectangle this R must be the lowerbound.
B = R
End If
End If
indx += 1
End While
Return result
当然,整体解决方案是: 找到每个点P,在opt(P,Left),opt(P,Right),opt(P,Top),opt(P,Bottom)中的最佳值,然后找到所有P的最大值。 Right,Top,Bottom的品种当然与我在上面勾勒出的opt(左)非常相似。 预排序(获取x顺序和y顺序(用于处理(P,Top)和(P,Bottom) - 的索引)是O(nLogn),局部优化是O(n) - 查看代码。因此总体复杂度为O(n ^ 2)。
注意添加 - 因为原始配方对我来说并不是绝对清楚: 如果矩形也可以由CORNER点限定,那么上面需要一些微小的调整(大多数是对不等式条件添加等号),但它本质上不会改变算法。
答案 1 :(得分:1)
你真的不需要四分 找到形成矩形形状的topLeft和bottomRight Point 循环遍历数组,只需跟踪/更新这两点 一旦退出循环就回来了 (topLeft.x - bottomRight-x)*(topLeft.y - bottomRight-y);
你去了
答案 2 :(得分:1)
我可以在O(N^2*Log(N))
中执行此操作。
首先将所有点放在一个集合中,以便我们检查O(Log(N))
中是否存在一个点。
枚举对角线上的2个点,花费O(N^2)
,然后确定矩形,检查是否存在其他2个点然后你知道是否可以得到它,如果你这样做,则更新答案。
答案 3 :(得分:0)
最简单的方法是计算while循环中的所有可能区域,并在结尾处获取最大区域。
答案 4 :(得分:0)
def max_area_rectangle(points):
seen_points = set()
max_area = float('-inf')
for x1, y1 in points:
for x2, y2 in seen_points:
if (x1, y2) in seen_points and (x2, y1) in seen_points:
area = abs(x1 - x2) * abs(y1 - y2)
if area > 0 and area > max_area:
max_area = area
seen_points.add((x1, y1))
#return area if it was possible to compute otherwise None
return max_area if max_area > float('-inf') else None