在2D阵列中查找局部最大值

时间:2012-03-20 04:25:22

标签: algorithm max

2D数组中的局部最大值可以定义为一个值,使得它的4个邻居都小于或等于它,即a[i][j]是局部最大值,

a[i+1][j] <= a[i][j] 
&& a[i-1][j] <= a[i][j]
&& a[i][j+1] <= a[i][j]
&& a[i+1][j-1] <= a[i][j]

我被要求找到给定2D阵列中的所有局部最大值。

这样做的天真方法是遍历所有元素,并检查每个元素是否是局部最大值。这将是O(n ^ 2)。虽然我的朋友坚持认为应该存在渐近更好的算法,但我觉得你做不到这一点。任何提示?

我正在思考Divide and Conquer的思路,但我觉得如果不经过所有数字就不可能检测到所有的局部最大值,而这些数字必然是O(n ^ 2)。我是对的还是我错过了什么?

7 个答案:

答案 0 :(得分:12)

只需要抬头,2D网格的局部最大值或最小值可以使用分而治之策略在O(nlgn)时间内计算。这比O(n ^ 2)时间复杂度类中包含的强力算法稍微好一点。此外,可以对分而治之算法进行改进,以获得用于2D网格极值发现的O(n)算法。

查看这些峰值拣选算法背后的理论说明(我相信它们的材料更多):

http://courses.csail.mit.edu/6.006/spring11/lectures/lec02.pdf

答案 1 :(得分:3)

除非你的数组是正方形,否则你的解决方案实际上是O(I * J)而不是O( n^2 )。严格来说,您的2d数组中只有N元素,因此此解决方案为O(N)。唯一的方法是O( n^2 ),如果数组是方形的I = J = N

由于比较是<=而不是<,您仍需要检查下一个元素,您尝试的任何快捷方式都可能是特定于处理器的。

  

最糟糕的情况是整个数组是局部最大值,因为   整个数组等于相同的值。

因此,您必须访问每个元素一次,使其成为O(N)

为了提高现实世界的性能,您需要使用指针访问您的数组,因为在大多数语言中,2d数组的性能比1d数组差得多。

答案 2 :(得分:0)

我相信这个问题可以用所谓的对手参数来回答,这会给你一个比较次数的下限。

在我看来,你说得对..这需要至少n ^ 2次比较。

答案 3 :(得分:0)

我很确定这不能在O(n ^ 2)比较中解决。假设棋盘2d矩阵,其中所有白色方块都是1,黑色是0.它将有O(n ^ 2)个解,每个解决方案至少需要一次比较。

答案 4 :(得分:0)

你不必参观每个元素:

你所要做的就是将网格可视化,你会发现这可以用比平面n ^ 2(或I * J)小得多的方法来解决。 以下是按级别进行的优化:

1]对于I * J矩阵,您只需要搜索(I-2)*(J-2)。为什么?由于未定义的元素,边界不能是最大值:

 e.g. grid[0][J] or grid[I][0] could never be maxima. because of the -1 neighbor.

因此,对于10乘12的网格,我们不是访问所有120个元素,而是查看80个元素。

2]如果grid [I] [J]是最大值,那么我们可以在继续搜索时跳过与[I] [J]相邻的所有单元格。这将进一步减少要比较的元素数量。

因此,答案是否定的,您不必访问每个元素。

答案 5 :(得分:0)

以上答案只是捍卫数学模型 这是对问题的简单看法的结果。

如果您是程序员,您应该知道处理器可以做什么。 你应该知道代码在一个线程中运行。 您应该想知道一个任务是否可以在较小的任务中进行细分,因此您可以将其用于多线程并接近1 /总线程执行速度。

执行此操作的代码取决于语言,因此我在此处不提供示例。

答案 6 :(得分:0)

您将得到一个大小为4 x 4的数组。您将需要执行以下任务。

  1. 使用rand()函数用一些随机数填充数组。

  2. 对于每个像元(i,j),您将需要在该像元(i,j)具有的所有可能邻居中找到具有最大数目的像元。

  3. 然后将最大数量放入该单元格(i,j)

样本输入:

177 -90 12 7
1 34 43 67
11 11 122 45
6 90 98 93

样本输出:

34 177 67 67
177 177 122 122
90 122 98 122
90 98 122 122