二分查找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)