二进制搜索算法实现
Binary Search algorithm implementations
我遇到过多个问题,这些问题使用 二分搜索 的变体来得出最终答案。这些问题包括找到数字平方根的下限、检查数字是否是完全平方数、在旋转数组中找到最小值、在数组中找到数字的第一个索引等。
所有算法都包含经过适当修改的低、高和中变量。
我在网上阅读了这些算法的几种变体,这些算法总是很可能出现一个错误,导致它错过极端情况。对于以下变体,是否有任何标准可以帮助我理解何时应该使用哪个?
1.变量初始化
选项 1:低 = 0,高 = arr.length
选项 2:低 = 0,高 = arr.length - 1
选项 1:低 = 1,高 = arr.length
2。循环条件
选项 1:同时(低 < 高)
选项 2:同时(低 <= 高)
3。中变量计算
选项 1:中 = (低 + 高) / 2;
选项2:中=低+(高-低)/ 2;
4。条件检查和更新到低和高
选项 1:低 = 中 AND 高 = 中
选项 2:低 = 中 AND 高 = 中 - 1
选项 3:低 = 中 + 1 AND 高 = 中
选项 4:低 = 中 + 1 AND 高 = 中 - 1
编辑:采用的假设是 3 态输出。数组索引从 0 开始。
您提到的选项并没有更好和更差。通常它只取决于一个实现,例如如果你通过 high=arr.length
那么你宁愿写 while(low < high)
而不是 while(low <= high)
.
事实上,其中一些 差异可能有意义 。如果我们考虑使用二进制搜索算法在数组 A 中找到你的 X 数,并且会有一些(不仅仅是一个)元素等于 X,你可以找到第一个或最后一个的索引 - 这取决于实现。
好吧,您可以通过多种方式使其发挥作用,但是:
1) 我用low=0, high=arr.length
。如果我要调用变量 low
和 high
,那么我希望始终使用 low<=high
,即使在搜索结束时也是如此。 arr.length==0
时这样也比较容易想到
2) while (low<high)
。这对应于 (1) 的答案。当循环完成后,我喜欢low==high
,所以我不必担心使用哪个
3) 始终使用 mid=low+(high-low)/2
或 mid = low+((high-low)>>1)
。当数组太长并给出负面结果时,另一个选项会溢出。
4) 这取决于您使用的比较类型(三态与二态输出),以及其他答案。对于 2 态比较和上述答案,您会得到 low=mid+1
或 high=mid
。这是理想的,因为很明显每次迭代范围都会变小——mid+1 > low
显然,而 mid < high
,因为 low<high
(这是循环条件)和 (high-low)/2
向下舍入.
我遇到过多个问题,这些问题使用 二分搜索 的变体来得出最终答案。这些问题包括找到数字平方根的下限、检查数字是否是完全平方数、在旋转数组中找到最小值、在数组中找到数字的第一个索引等。
所有算法都包含经过适当修改的低、高和中变量。
我在网上阅读了这些算法的几种变体,这些算法总是很可能出现一个错误,导致它错过极端情况。对于以下变体,是否有任何标准可以帮助我理解何时应该使用哪个?
1.变量初始化
选项 1:低 = 0,高 = arr.length
选项 2:低 = 0,高 = arr.length - 1
选项 1:低 = 1,高 = arr.length
2。循环条件
选项 1:同时(低 < 高)
选项 2:同时(低 <= 高)
3。中变量计算
选项 1:中 = (低 + 高) / 2;
选项2:中=低+(高-低)/ 2;
4。条件检查和更新到低和高
选项 1:低 = 中 AND 高 = 中
选项 2:低 = 中 AND 高 = 中 - 1
选项 3:低 = 中 + 1 AND 高 = 中
选项 4:低 = 中 + 1 AND 高 = 中 - 1
编辑:采用的假设是 3 态输出。数组索引从 0 开始。
您提到的选项并没有更好和更差。通常它只取决于一个实现,例如如果你通过 high=arr.length
那么你宁愿写 while(low < high)
而不是 while(low <= high)
.
事实上,其中一些 差异可能有意义 。如果我们考虑使用二进制搜索算法在数组 A 中找到你的 X 数,并且会有一些(不仅仅是一个)元素等于 X,你可以找到第一个或最后一个的索引 - 这取决于实现。
好吧,您可以通过多种方式使其发挥作用,但是:
1) 我用low=0, high=arr.length
。如果我要调用变量 low
和 high
,那么我希望始终使用 low<=high
,即使在搜索结束时也是如此。 arr.length==0
2) while (low<high)
。这对应于 (1) 的答案。当循环完成后,我喜欢low==high
,所以我不必担心使用哪个
3) 始终使用 mid=low+(high-low)/2
或 mid = low+((high-low)>>1)
。当数组太长并给出负面结果时,另一个选项会溢出。
4) 这取决于您使用的比较类型(三态与二态输出),以及其他答案。对于 2 态比较和上述答案,您会得到 low=mid+1
或 high=mid
。这是理想的,因为很明显每次迭代范围都会变小——mid+1 > low
显然,而 mid < high
,因为 low<high
(这是循环条件)和 (high-low)/2
向下舍入.