【发布时间】: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?
【问题讨论】:
简单问题和已知算法:
我有一个包含 100 个成员的大数组。前 X 个成员为 0,其余为 1。求 X。
我通过二分查找来解决它:检查成员 50,如果是 0 - 检查成员 75,等等,直到找到相邻的 0 和 1。
我正在为相同的二维问题寻找优化算法:
我有 100*100 的二维数组。行 0-X AND 列 0-Y 的成员为 0,其余为 1。如何找到 Y 和 X?
【问题讨论】:
运行您的二分搜索两次。先对最后一行进行二分查找确定X,再对最后一列进行二分查找确定Y。
【讨论】:
简单的解决方案:先在 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 提出有趣的问题。 :)
【讨论】:
在两个维度和一维情况下使用二分搜索:
【讨论】:
编辑:最佳解决方案包括两个简单的二分搜索。
对于我在下面发表的冗长而复杂的帖子,我深表歉意。问题的根本在于在包含 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)) 的值。然后,当您要在a 和b 之间剪切值时,选择剪切点为a + factor*(b-a)。当您在点 (100*factor, 100*factor) 处切割初始 100x100 矩形时,两个区域的面积将是 (100*100)/2,因此收敛速度会更快。
【讨论】: