我知道 Saddle back搜索算法可以在 O(n)时间内找到排序的2d数组中的元素(数组已排序)在X维度和Y维度上(或称之为2d square 矩阵),没有重复。从我读过的所有文章来看,它似乎是2d平方排序矩阵的最优算法。对于那些不知道鞍背算法如何工作的人:
想象2d数组为2d矩阵。
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
示例:
在下面的2d排序数组中找到54。
现在,如何有效地修改此算法,以搜索2d排序数组中元素的所有出现,该数组可以包含重复。 示例: 在下面的数组中查找54的所有出现。
答案 0 :(得分:0)
您可以按如下方式递归地重复使用该算法。在索引(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
}