【问题标题】:Looking for an algorithm (version of 2-dimensional binary search)寻找算法(二维二分搜索的版本)
【发布时间】:2011-10-18 01:48:16
【问题描述】:

简单问题和已知算法:

我有一个包含 100 个成员的大数组。前 X 个成员为 0,其余为 1。求 X。

我通过二分查找来解决它:检查成员 50,如果是 0 - 检查成员 75,等等,直到找到相邻的 0 和 1。

我正在为相同的二维问题寻找优化算法:

我有 100*100 的二维数组。行 0-X AND 列 0-Y 的成员为 0,其余为 1。如何找到 Y 和 X?

【问题讨论】:

    标签: algorithm binary-search


    【解决方案1】:

    运行您的二分搜索两次。先对最后一行进行二分查找确定X,再对最后一列进行二分查找确定Y。

    【讨论】:

      【解决方案2】:

      简单的解决方案:先在 X 方向,然后在 Y 方向。

      检查 (0,50);如果是0,检查(0,75);直到找到相邻的 0 和 1。然后从那里转到 Y 方向。

      第二种解决方案:

      检查成员 (50,50)。如果是 1,检查 (25,25),直到找到 0。继续,直到找到相邻的 (X,X) 和 (X+1,X+1) 为 0 和 1。然后测试 (X,X +1) 和 (X+1,X)。两者都不是或其中之一将是 1。如果两者都不是,你就完了。如果只有一个,例如 (X+1,X),那么您知道框的大小介于 (X+1,X) 和 (100,X) 之间。使用二分搜索查找框的高度。

      编辑:正如 Chris 指出的那样,简单的方法似乎更快。

      第二个解决方案(修改):

      检查成员 (50,50)。如果是 1,检查 (25,25),直到找到 0。继续,直到找到相邻的 (X,X) 和 (X+1,X+1) 为 0 和 1。然后测试 (X,X +1)。如果为 1,则在 (X,X+1)...(X,100) 行上进行二分查找。否则在 (X,X)...(100,X) 行上进行二分搜索。

      即使那样,我也可能在这里打死马。如果它会更快,那么可以忽略不计。这只是为了理论上的乐趣。 :)

      EDIT 2 正如 Fezvez 和 Chris 所说,二分搜索将搜索空间一分为二最有效;我的方法将区域划分为 1/4 和 3/4 块。 Fezvez 指出,这可以通过预先计算除法因子来解决(但这将是额外的计算)。在我的算法的修改版本中,我选择要去的方向(X 或 Y 方向),这也有效地将搜索空间一分为二,然后进行二分搜索。总而言之,这表明这种方法总是会慢一些。 (而且实现起来更复杂。)

      感谢 Igor Oks 提出有趣的问题。 :)

      【讨论】:

      • 我喜欢这种方法。它实际上是同时在 X 和 Y 上进行二进制搜索,直到您确定一个,然后继续找到另一个已经缩小了搜索范围。比单独做 X 和 Y 更有效。
      • @Chris:这绝对不会比独立进行两次搜索更有效。那是因为这里的搜索空间是二次方大的。所以理论上的大 O 复杂度是相同的 log(N*N) == 2*log(N)。这个解决方案不那么简单而且更复杂。我认为这种解决方案的效率不如两次独立搜索,因为它不会在每次迭代时均分搜索空间。
      • 我的帖子可能不清楚,但我打算将其作为二进制搜索。 (平均划分搜索空间)。此外,Big O 复杂性是一回事,运行时是另一回事。我会假设这个程序平均快 x 倍,其中 1
      • 嗯...不要告诉我的老板,但我写了一个程序来测试这个...看起来独立的方法更快。看起来这主要是由于需要进行 2 次额外测试来确定您在对角线上找到的东西是 X 还是 Y 的边缘。随着您的搜索区域大小的增加,这 2 变得不那么重要但总是足以摆动它看来。
      • 我认为 Fezvez 在他的回答中说得最好,要做到这一点,您需要做的就是在每个步骤中将搜索空间分成两半并丢弃它。 x first then y 方法以非常简单的方式执行此操作,我认为其他任何事情,尤其是需要额外检查以确定要丢弃哪个部分的事情,都不会更快。
      【解决方案3】:

      在两个维度和一维情况下使用二分搜索:

      1. 从 j=50 开始。现在通过改变 i 获得的一维数组具有所需的形式 - 所以从一维案例中找到 X。
      2. 如果 X = 100(即没有一个),则使 j=75(j 维范围的中间)并重复。
      3. 如果 X

      【讨论】:

        【解决方案4】:

        编辑:最佳解决方案包括两个简单的二分搜索。

        对于我在下面发表的冗长而复杂的帖子,我深表歉意。问题的根本在于在包含 100*100 个元素的空间中找到一个点。你能做的最好的就是在每一步把这个空间分成两部分。你可以用一种复杂的方式来做(我在帖子的其余部分做的那个)但是如果你意识到在 X 轴上的二分搜索仍然在每一步将研究空间分成两部分,(同样适用于 Y轴)然后你就会明白它是最优的。

        我还是让我做的事情,对不起,我在里面做了一些强制性的肯定。


        如果您正在寻找一种简单的算法(尽管不是最优的),只需按照建议运行两次二分搜索即可。

        但是,如果您想要一个最优算法,您可以同时寻找 X 和 Y 上的边界。 (需要注意的是,这两种算法的渐近复杂度是一样的,但是最优的算法还是会更快)

        在以下所有图形中,点 (0, 0) 位于左下角。

        基本上,当您选择一个点并获得结果时,您会将空间分成两部分。当您考虑它时,这实际上是您可以从中提取的最大信息量。

        如果您选择点(黑色十字),结果为 1(红线),这意味着您要查找的点在灰色空间中(因此必须在剩余的白色区域)

        另一方面,如果值为 0(蓝线),这意味着您要查找的点可能在灰色区域(因此必须在剩余的白色区域)

        所以,如果你得到一个 0 结果和一个 1 结果,你会得到:

        您要查找的点在矩形 1、2 或 3 中。您只需检查矩形 3 的两个角,即可知道这 3 个矩形中哪个是好的。

        所以算法如下:

        • 注意您正在使用的矩形的左下角和右上角在哪里。

        • 沿矩形的对角线进行二分搜索,直到您至少偶然发现一次结果为 1 和一次结果为 0。

        • 检查矩形 3 的另外 2 个角(你必须已经知道对角线上两个角的值) 可以只检查一个角来知道正确的矩形(但你会如果右边的矩形是矩形,则必须检查两个角 3)

        • 确定您要查找的点是否在矩形 1、2 或 3 中

        • 通过将问题减少到好的矩形重复,直到最终的矩形减少到一个点:这是您正在寻找的值


        编辑:如果您想要最高最优性,那么当您选择点 (50, 50) 时,您不会等分切割空间。一个比另一个大三倍。理想情况下,您将选择一个将空间分割成两个相等区域(区域)的点

        您应该在开始时计算一次factor = (1.0 - 1.0/sqrt(2.0)) 的值。然后,当您要在ab 之间剪切值时,选择剪切点为a + factor*(b-a)。当您在点 (100*factor, 100*factor) 处切割初始 100x100 矩形时,两个区域的面积将是 (100*100)/2,因此收敛速度会更快。

        【讨论】:

        • 这似乎是对 Rauni 建议的算法的更好解释。但正如我在那里指出的那样,我想知道它是否真的比两个线性搜索更快。看起来它只是更复杂。
        • 你说的很有趣,是的,它们很相似。 Rauni 算法所做的是它不断搜索蓝线和红线,直到剩余的矩形为 1 个“像素”宽。然后,它搜索 (X, X+1) 和 (X+1, X),这与查找第三个矩形的另外 2 个角相同。现在,关于复杂性,我不太确定。我只是认为,当你进行一次线性搜索时,你会丢弃一半的信息(你不关心另一个轴),而在这里,所有的信息都会被考虑在内。
        • @Fezvez:您的 cmets 在编辑二进制搜索主要只是想将空间一分为二这一事实是我一直在努力得出的一个极好的见解。 +1 仅此而已。 :)
        • @Chris:谢谢!好吧,我很生气没有搜索这么多,但我很高兴指出这样一个事实,即您在每次迭代中真正想要做的是将空间分成两半!感谢您的支持! =)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-23
        • 1970-01-01
        • 2021-05-26
        • 2017-07-02
        相关资源
        最近更新 更多