【问题标题】:modify saddleback search to handle duplicates修改鞍背搜索以处理重复项
【发布时间】:2014-11-06 19:44:28
【问题描述】:

我知道 鞍背搜索算法 可以在 O(n) 时间内在 已排序的二维数组(数组已排序在 X 维和 Y 维中)(或称其为已排序的 2d square 矩阵),没有重复项。从我读过的所有文章来看,它似乎是二维平方排序矩阵的最佳算法。对于那些不知道鞍背算法如何工作的人:

将二维数组想象为二维矩阵。

1. Start at the top-left corner. i.e.  Initialize row to its maximum value and column to its minimum value.
2. Check at (row, column). If it’s value is less than the target value, then increase column by one.
3. If it's greater than the target value, then decrease row by one. 
4. Do this until we reach the element or boundary

示例:

在下面的二维排序数组中找到 54。

现在我如何以一种有效的方式修改此算法以搜索二维排序数组中可能有重复项的元素的所有出现示例: 在下面的数组中找到所有出现的 54。

【问题讨论】:

  • 找到匹配项后,尝试按降序进行,直到找到不同的值。接下来从发生点往上升的方向走,当值不同时停止。
  • 如果你降落在中间的 34 值,向左走直到没有更多的 34。这是起点。向右走,直到没有更多的 34。这是结束标记。由于矩阵是排序的,根据定义,所有相同的值都将放在一起,除非矩阵没有重复项。否则,请澄清“搜索所有出现”的含义。
  • 您的第二张图显示了算法的错误执行。
  • @TheGame:对。你能弄清楚如何追踪一大块 54 的上下轮廓吗?这是唯一缺少的成分。
  • @ThomasMatthews:通过“搜索所有出现”我的意思是找到所有 (x,y) 其中 arr[x,y] = 54

标签: c++ c arrays algorithm data-structures


【解决方案1】:

您可以递归地重用该算法,如下所示。一旦您在索引(i, j) 处找到目标值,您希望再次对两个子矩阵执行该算法:M[i+1:m, j]M[i:m, j+1:n]。第一种情况很简单,因为它是单列,并且您知道所有/任何出现都在列的顶部。一旦您在该列中找到了所有匹配项,您就可以将完全相同的算法应用于子矩阵M[i:m, j+1:n],即严格位于找到的位置右侧且位于其行或低于其行的值。

当矩阵中的每个值都是目标值时,您可以在问题中做的最好的最坏情况发生,导致 O(m*n) 比较。这个递归版本可以做到这一点,它的性能通常是 O(m+n+x),其中 x 是共享一列的出现次数。

伪代码:

// assume M is non-ascending going down (+rows) and non-descending going right (+cols)
findOccurrences(Matrix M, Value target) {
    (List of Pair of int and int) result = {}
    int i, j = 0
    while( i < M.rows && j < M.cols )
        if( M[i, j] < target )
            j = j + 1
        else if( M[i, j] > target )
            i = i + 1
        else
            int k = i
            while( k < M.rows && M[k, j] == target )
                result.append({k, j})
                k = k + 1
            // we have found all occurrences in column j
            // there may be any number of occurrences left
            // in the submatrix to the right of i,j but
            // below or at i so just continue with the next j
            j = j + 1
    return result
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-14
    • 2018-12-04
    • 1970-01-01
    • 1970-01-01
    • 2011-02-06
    • 2011-10-07
    • 1970-01-01
    相关资源
    最近更新 更多