分析
以二分查找最后一次 left = n - 1,right = n 举例进行分析。
第一种情况:
| 1 | while (left < right) { | 
此时 mid = n - 1,如果 check(mid) = true,那么 left = mid + 1 = n,可以正常结束循环;如果 check(mid) = false,那么 right = mid = n - 1,同样可以正常结束循环。
这个时候的查找结果偏向于 right,以 升序区间 来说,相当于 大于等于 的情况。
第二种情况:
| 1 | while (left < right) { | 
此时 mid = n - 1,如果 check(mid) = true,那么 left = mid = n - 1,进入死循环;如果 check(mid) = false,那么 right = mid - 1 = n - 2,right < left 虽然可以正常结束循环,但是没有准确的结果(因为不知道结果是 left 还是 right)。
第三种情况:
| 1 | while (left < right) { | 
此时 mid = n,如果 check(mid) = true,那么 left = mid + 1 = n + 1,虽然可以正常结束循环,但是没有准确的结果(因为不知道结果是 left 还是 right);如果 check(mid) = false,那么 right = mid = n,进入死循环。
第四中情况:
| 1 | while (left < right) { | 
此时 mid = n,如果 check(mid) = true,那么 left = mid = n,可以正常结束循环;如果 check(mid) = false,那么 right = mid = n - 1,同样可以正常结束循环。
这个时候的查找结果偏向于 left,以 升序区间 来说,相当于 小于等于 的情况。
结论
- int mid = left + (right - left >> 1)配合着- left = mid + 1使用;- int mid = left + (right - left + 1 >> 1)配合着- right = mid - 1使用。需要注意的是- >>的运算优先级要低于- +-。
- 使用 - left = mid + 1,查找结果偏向于- right,以 升序区间 来说,相当于 大于等于 的情况;使用- right = mid - 1,查找结果偏向于- left,以 升序区间 来说,相当于 小于等于 的情况。
算法模板
第一种
查找结果偏向于 right,以 升序区间 来说,相当于 大于等于 的情况。
| 1 | int left = 0; | 
第二种
查找结果偏向于 left,以 升序区间 来说,相当于 小于等于 的情况。
| 1 | int left = 0; | 
__END__
