矩阵中的最小迭代次数,其中单元迭代中的单元格值被最大相邻单元格值替换

时间:2017-05-31 19:02:25

标签: python algorithm matrix

我有一个矩阵,每个单元格中的值(最小值= 1),其中最大值是' max'。

每次,我将每个单元格值修改为其相邻单元格的最高值,即所有8个邻居,并且这同时发生在整个矩阵中。我希望在最小迭代次数之后找到所有单元格的最大值。

这样做的一种强力方法是用零填充矩阵,

for i in range (1,x_max+1):
    for j in range(1,y_max+1):
    maximum = 0 
        for k in range(-1,2):
            for l in range(-1,2):
                if matrix[i+k][j+l]>maximum:
                    maximum = matrix[i+k][j+l]
        matrix[i][j] = maximum

但有没有一种智能且更快捷的方法呢? 提前谢谢。

3 个答案:

答案 0 :(得分:4)

我认为这可以通过BFS(广度优先搜索)来解决。

使用' max'与所有矩阵单元同时启动BFS。值。

  dis[][]  == infinite // min. distance of cell from nearest cell with 'max' value, initially infinite for all
  Q // Queue
  M[][] // matrix
  for all i,j   // travers the matrix, enqueue all cells with 'max'
    if M[i][j] == 'max' 
       dis[i][j] = 0 , Q.push( cell(i,j) )
  while !Q.empty:
       cell Current = Q.front 
       for all neighbours Cell(p,q) of Current: 
              if dis[p][q] == infinite
                 dis[p][q] = dis[Current.row][Current.column] + 1
                 Q.push( cell(p,q))
       Q.pop()

所有i,j的max(dis [i] [j])单元格将为no。需要迭代。

答案 1 :(得分:1)

使用带有" border"。

的数组

测试边缘条件是繁琐的,可以通过使数组在边缘周围变大1来避免,每个元素的值为INT_MIN

此外,考虑8个测试,而不是双嵌套循环

// Data is in matrix[1...N][1...M], yet is size matrix[N+2][M+2]
for (i=1; i <= N; i++) {
  for (j=1; j <= M; j++) {
    maximum = matrix[i-1][j-l];
    if (matrix[i-1][j+0] > maximum) maximum = matrix[i-1][j+0];
    if (matrix[i-1][j+1] > maximum) maximum = matrix[i-1][j+1];
    if (matrix[i+0][j-1] > maximum) maximum = matrix[i+0][j-1];
    if (matrix[i+0][j+0] > maximum) maximum = matrix[i+0][j+0];
    if (matrix[i+0][j+1] > maximum) maximum = matrix[i+0][j+1];
    if (matrix[i+1][j-1] > maximum) maximum = matrix[i+1][j-1];
    if (matrix[i+1][j+0] > maximum) maximum = matrix[i+1][j+0];
    if (matrix[i+1][j+1] > maximum) maximum = matrix[i+1][j+1];
    newmatrix[i][j] = maximum

答案 2 :(得分:1)

所有现有答案都需要检查矩阵中的每个单元格。如果您还不知道最大值的位置是什么,这是不可避免的,在这种情况下,Amit Kumar's BFS algorithm具有最佳时间复杂度:O(wh),如果矩阵具有宽度w和高度h。

OTOH,也许你已经知道k个最大值的位置,k相对较小。在这种情况下,以下算法将在O(k ^ 2 *(log(k)+ log(max(w,h))))时间内找到答案,当w或h很大时,这个时间要快得多。它实际上并没有查看任何矩阵条目;相反,它运行二进制搜索以查找候选停止时间(即答案)。对于每个候选停止时间,它构建了那时将被max占用的矩形集,并检查是否有任何矩阵单元仍被矩形覆盖。

为了解释这个想法,我们首先需要一些术语。将矩形的顶行称为“起始垂直事件”,将其底部边缘下方的行称为“结束垂直事件”。 “基本间隔”是由任何一对垂直事件跨越的行的间隔,它们之间没有任何第三个垂直事件(定义这些间隔的事件对可以来自相同或不同的矩形)。请注意,对于k个矩形,永远不会有超过2k + 1个基本区间 - 这里对h没有依赖性。

基本思路是从左到右穿过与水平事件对应的矩阵列:新的矩形“开始”的列(左边的垂直边缘)矩形),或现有的矩形“完成”(矩形的右垂直边缘右侧的列),跟踪当前覆盖每个基本区间的矩形数量。如果我们检测到由0个矩形覆盖的基本区间,我们可以停止:我们找到了一个包含一个或多个在时间t尚未覆盖的单元格的列。如果我们到达矩阵的右边缘而没有发生这种情况,那么在时间t覆盖所有单元格。

这是一个函数的伪代码,在给定长度为k的数组t的情况下检查是否有任何矩阵单元未被时间peak覆盖,其中(peak[i].x, peak[i].y)是i的位置th max - 包含原始矩阵中的单元格,按x坐标的递增顺序排列(因此最左边的max - 包含的单元格位于(peak[1].x, peak[1].y))。

Function IsMatrixCovered(t, peak[]) {
    # Discover all vertical events and basic intervals
    Let vertEvents[] be an empty array of integers.
    For i from 1 to k:
        top = max(1, peak[i].y - t)
        bot = min(h, peak[i].y + t)
        Append top to vertEvents[]
        Append bot+1 to vertEvents[]

    Sort vertEvents in increasing order, and remove duplicates.

    x = 1
    Let horizEvents[] be an empty array of { col, type, top, bot } structures.

    For i from 1 to k:
        # Calculate the (clipped) rectangle that peak[i] will cover at time t:
        lft = max(1, peak[i].x - t)
        rgt = min(w, peak[i].x + t)
        top = max(1, peak[i].y - t)
        bot = min(h, peak[i].y + t)

        # Convert vertical positions to vertical event indices
        top = LookupIndexUsingBinarySearch(top, vertEvents[])
        bot = LookupIndexUsingBinarySearch(bot+1, vertEvents[])

        # Record horizontal events
        Append (lft, START, top, bot) to horizEvents[]
        Append (rgt+1, STOP, top, bot) to horizEvents[]

    Sort horizEvents in increasing order by its first 2 fields, with START considered < STOP.

    # Walk through all horizontal events, from left to right.
    Let basicIntervals[] be an array of size(vertEvents[]) integers, initially all 0.
    nOccupiedBasicIntervalsFirstCol = 0
    For i from 1 to size(horizEvents[]):
        If horizEvents[i].type = START:
            d = 1
        Else (if it is STOP):
            d = -1

        If horizEvents[i].col <= w:
            For j from horizEvents[i].top to horizEvents[i].bot:
                If horizEvents[i].col = 1 and basicIntervals[j] = 0:
                    ++nOccupiedBasicIntervalsFirstCol      # Must be START
                basicIntervals[j] += d
                If basicIntervals[j] = 0:
                    return FALSE

    If nOccupiedBasicIntervalsFirstCol < size(basicIntervals):
        return FALSE         # Could have checked earlier, but the code is simpler this way

    return TRUE
}

上面的函数可以简单地在t上的二进制搜索中调用,它查找函数返回TRUE的最小t值。

通过使用Fenwick trees,利用任何矩形开始或结束的基本区间集合总是一个区间这一事实,可以消除k / log(k)的另一个因子。