算法 - 在网格中找到四个元素,这些元素构成一个矩形,最小值为最大值

时间:2014-04-01 16:23:54

标签: algorithm

我有一个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),我们检查矩形中可能与其相对的每个元素。在下面的示例中,当我们检查红色元素时,可能的元素是黄色元素。

enter image description here

这样的解决方案显然是O(n^4),这是不可取的。

任何人都知道更好的方法吗?

1 个答案:

答案 0 :(得分:1)

O(n 3 )算法

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 log n)算法

与以前的方法不同,这个方法需要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)