我有一个2D数组,其中值是单调的。如何找到所有(x,y)其中| f(X,Y) - v1 | <以最好的方式。
答案 0 :(得分:10)
在具有已排序行和列的矩阵中搜索值是一个经典问题。将row
初始化为其最大值,将column
初始化为其最小值。检查row, column
处的矩阵条目。如果它小于目标值,则将column
增加1。如果它大于目标值,则将row
减1。检查的矩阵条目数最多为#rows + #columns - 1
。
如果在找到目标值后继续此搜索,则将row
减少一个(分别增加column
一个),然后我们获得副产品确定哪些元素小于(分别,小于或等于)目标值。执行此搜索算法2 | V |使用不同目标值(小于或等于v_i - t
,小于v_i + t
)的时间来解决检查O(| V | n)矩阵元素的问题。
可以进行各种优化。最明显的是缓存矩阵值。另一种方法是,使用无界二进制搜索来确定最合适的增量/减量,而不是只用一步。目前还不清楚相邻条目的大幅变化是否可以克服较高的最坏情况常数因素。
使用Mooing Duck的例子:
To look for elements in the range (48, 52),
look for elements less than or equal to 48
and (separately) elements less than 52.
Looking for elements less or equal to 48:
Go right (>) if the current element is less than or equal to 48.
Go down (v) if the current element is greater than 48
50 60 70 80 90 100
v
40 > 51 60 70 80 90
v
30 50 52 55 70 80
v
30 40 > 45 > 46 > 51 52
v
30 40 42 45 50 51
v
30 40 41 44 49 50
v
done (access would be out of bounds)
The elements less than or equal to 48 are those in some submatrix containing
an examined element found to be less than or equal to 48
and elements to the left and below.
答案 1 :(得分:2)
让我把我的评论转为答案:
可以在最多4个n - 3个评估中解决 n × n 问题,并且我猜想这个边界是最优的,或至少接近最佳状态。
算法如下:
从左上角开始,即 x = 1, y = n 。
评估函数 f ( x , y )。如果 f ( x , y )< v 1 + t ,增加 x ,否则递减 y 。
从步骤2开始重复,直到 y < 1或 x > n ,即直到你碰到网格的底部或右边缘。
您现在已经找到了区域的上边缘 - t < f ( x , y ) - v 1 < 吨。现在对下边缘做同样的事情;也就是说,应用上面的算法,但用 f ( x , y )替换步骤2中的条件< v 1 - t 。
每个边缘最多需要2个 - 1个函数评估,并且它们至少在一个点上重叠( x = 1, y = n ),所以4
虽然我还没有设法证明上面给出的算法的最优性,但是我可以证明任何解决方案必须至少需要2个 - 2个函数评估。最坏的情况。具体来说,我可以在 n × n 网格上展示一系列双向功能 f ,这样即使的值也是如此f 除了2
f ( x , y )= x 给出了这类功能系列的示例+ y + ε( x , y ), v 1 = n + 1, t = 1,| ε( x ,ÿ)| < 1表示所有 x , y 。很容易看出这些函数在 x 和 y 中都是单调递增的(至少在限制为网格点时),并且:
不确定的超级和次级对角线各包含 n - 1个点,每个点需要单独测试 - 我们可以自由选择函数ε( x , y )以使这些点的任何子集落在容差区域内。因此,即使具有这种额外的先进知识,也需要至少2 n-2次测试来精确地确定公差区域的边界。
事实上,这个论点可以通过简单的调整来将下限提高到2 - 1.然而,超越它,似乎需要更复杂的论证,即使看起来直观明显在没有这些额外知识的情况下,在最坏的情况下,我们至少需要接近4 n 评估。不过,这个证明结合上面的算法,至少表明这个问题的最坏情况渐近复杂度是Θ( n )。
此外,在 d ≥3维,通过划分O( n d-1 )函数评估可以简单地解决这个问题将网格分成二维切片并将上面给出的算法分别应用于每个切片。此外,我相信上面下限证明的相当简单的推广可以用来表明这个问题的 d 维度版本的最坏情况复杂度确实是Θ(名词 d-1 )。
答案 2 :(得分:1)
您可以在O(2*log n + 4 * n)
找到单个值的所有积分。
首先,您应该找到第一行具有可接受值的点的间隔。您可以使用两个二进制搜索来执行此操作因此,您将获得c1
和c2
,|f(0, c) - v1| < t
c
[c1, c2]
。此初始步骤大约需要O(log n)
。
然后,由于函数在X和Y维度上都是单调递减的,因此您会知道当递增行时,这两个值c1
和c2
只会减少。由于您可以将它们总计递减c1 + c2 <= 2*n
次,并且因为您可以为这两个值增加行n
次,所以我们得到4*n
函数调用的上限。