🐶结构1辨析
这里介绍第一种结构
1 | function binary_search(A, n, T) is |
这里m := floor((L + R) / 2)有时会替换成m := ceiling((L + R) / 2),简单来说就是(L + R) / 2替换成(L + R + 1) / 2。
在以上结构中这个语句的替换不会影响算法的正确性。不过在目标T在数组A中有多个的时候,可能会影响到底返回多个T中的哪一个。
比如[1 2 2 2 3 4],在floor时返回的下标是2,在ceiling时返回的下标是3.
🦊优化1
这里有一个可以小优化的地方,L+R存在整形溢出的情况,可以改为L + (R - L) / 2避免溢出问题。
🐹结构2辨析
这其实也是一种优化,因为以上结构中在每个循环中比较次数太多,可以使用以下结构来代替。
1 | function binary_search_alternative(A, n, T) is |
或者
1 | function binary_search_alternative(A, n, T) is |
以上两种结构可以在每次循环中减少一次的比较。
并且值的注意的是以下两种结构是错误的:
1 | 👿function binary_search_alternative(A, n, T) is |
假设在[2 3 4]中查找2,
第一趟: L = 0 R = 5 m = 1 A[m] > T
第二趟: L = 0 R = 1 m = 1 A[m] > T
第三趟:L = 0 R = 1 m = 1 A[m] > T
…
第N趟:L = 0 R = 1 m = 1 A[m] > T
这里会导致无线循环,因为ceiling取上限,并且我们将m取在右边,导致区间在左边没法收敛。
同理,下面结构也是错误的:
1 | 👿function binary_search_alternative(A, n, T) is |
可以[2 3 4]中查找4来试试。
🙈结构3辨析
在存在重复元素的时候,究竟该返回哪一个呢?比如[1,2,4,4,4,5,6,7]查找4,是返回2还是3,或者4?
下面这样一个结构可以返回最左边的元素:
1 | function binary_search_leftmost(A, n, T): |
在找到元素后,依旧会通过R = m向左边收缩。
下面这样一个结构可以返回最右边的元素:
1 | function binary_search_rightmost(A, n, T): |
在找到元素后,依旧会通过left = m + 1向右边收缩。