二分查找cheat sheet
二分细节弄死人
总结一下吧。或者说直接出猫了。
来自这个题解
示例代码语言为Java
#
二分查找框架int binarySearch(int[] nums, int target) { int left = 0, right = ...;
while(...) { int mid = (right + left) / 2; if (nums[mid] == target) { ... } else if (nums[mid] < target) { left = ... } else if (nums[mid] > target) { right = ... } } return ...;}
- 技巧:不要出现 else,而是把所有情况用 else if 写清楚,这样可以清楚地展现所有细节。
- 思路:left 和 right 实际是控制一个当前的有效区间,但是区间是闭区间还是半开区间,就看不同情况了。
- 计算 mid 时需要技巧防止溢出,即
mid=left+(right-left)/2
。本文暂时忽略这个问题。
#
寻找一个数var searchTarget = function (nums, target) { let left = 0, right = nums.length - 1; while (left <= right) { let mid = Math.floor((left + right) / 2); if (nums[mid] === target) { return mid; } else if (nums[mid] < target) { left = mid + 1; } else { right = mid - 1; } } return -1;}
- 搜索区间:
[left, right]
闭区间 - 初始区间:
[0, len-1]
- 终止:mid找到target值;或区间为空
#
寻找左侧边界/第一个target值的位置
var searchLeftBorder = function (nums, target) { let left = 0, right = nums.length; while (left < right) { let mid = Math.floor((left + right) / 2); if (nums[mid] === target) { right = mid; } else if (nums[mid] < target) { left = mid + 1; } else { right = mid; } } return left;}
- 搜索区间:
[left, right)
半开区间 - 初始区间:
[0, len)
- 终止:
left === right
,区间为空;- 返回值也可以理解为nums中小于target的数字数量
#
寻找右侧边界/最后一个target值的位置var searchRightBorder = function (nums, target) { let left = 0, right = nums.length; while (left < right) { let mid = Math.floor((left + right) / 2); if (nums[mid] === target) { left = mid + 1; } else if (nums[mid] < target) { left = mid + 1; } else { right = mid; } } return left - 1;}
- 搜索区间:
[left, right)
半开区间 - 初始区间:
[0, len)
- 终止:返回
left - 1
,因为在循环中nums[mid] == target
时left = mid + 1 ==> mid = left - 1
,即nums[left - 1] == target
- 返回值可以理解为nums中小于等于target的数字数量-1(若不存在该target则不-1)