我有一个n x n
网格。所有网格都有数字。我需要在一个网格中找到4个点,这样它们就可以形成一个矩形,其中最小的元素尽可能大。最小值取自矩形的末端,即角元素。
实施例
1 1 1
2 1 2
3 1 4
答案是(2,1)
,(2,3)
,(3,1
)和(3,3)
,因为那时集合为2,2,3,4
,而min为2
1}},显然我们不能做得更好。
我能想到的唯一可能的解决方案就是蛮力。对于每个元素(它们的n^2
),我们检查矩形中可能与其相对的每个元素。在下面的示例中,当我们检查红色元素时,可能的元素是黄色元素。
这样的解决方案显然是O(n^4)
,这是不可取的。
任何人都知道更好的方法吗?
答案 0 :(得分:1)
for row1 = 1 .. n:
for row2 = row1 + 1 .. n:
h = empty min heap
for column = 1 .. n:
x = min(grid[row1, column], grid[row2, column])
push x to h
if h.size > 2:
pop h
best = max(best, h.min)
与以前的方法不同,这个方法需要O(n 2 )临时空间。
该算法基于二进制搜索,在处理有限范围内的整数时效果更好。因此需要简单的预处理来压缩网格中的值范围。按网格单元格的值对其进行排序,并用排序数组中的索引替换这些值。或者(如果原始值之间存在重复),我们可以为网格中的每个唯一编号分配连续的自然数(按排序顺序),在这种情况下,时间复杂度降低到O(n 2 log U) ,其中U
是唯一数字的数量。
range = [1 .. U] (where U is maximal cell value)
binary search, stop when range is empty:
m = range.middle
A = empty 2D array of size n*n
for row = 1 .. n:
L = empty linked list
for each column:
if grid[row, column] >= m:
append column to L
for column1 = L.begin .. L.end:
for column2 = column1.next .. L.end:
if A[column1, column2] is empty:
A[column1, column2] = row
else:
result = (A[column1, column2], row, column1, column2)
range = [m .. range.max]
continue binary search (found)
range = [range.min .. m]
continue binary search (not found)