这是跟着代码随想录的顺序学习算法的第?天。(二刷)
以下是学习时自己的一些理解与笔记,如有错误欢迎指正与讨论。
二分查找
参考相关链接:
笔记
const mid = left + Math.floor((right - left) / 2);
-
左闭右开即
[left, right)
,这意味着left
和right
不能同时取得或者说二者不能相等,否则这个区间是无效的。故对应的终止条件应为
left === right
,此时的while
判断条件应该为left < right
。区间右边是取不到的数,或者说是一定不符合要求的数,故初始化应为
right = nums.length
。 -
左闭右闭即
[left, right]
,这意味着left
和right
可以同时取得或者说二者可以相等,但left
不能比right
大,否则这个区间是无效的。故对应的终止条件应为
left === right + 1
,此时的while
判断条件应该为left <= right
。区间右边是取得到的数,或者说是有可能符合要求的数,故初始化应为
right = nums.length - 1
。
根据选定的区间类型来判断是需要使其是有可能符合要求的数,还是一定不符合要求的数(这里的 mid
就是一定不符合要求的数)
固定左边界,收缩右边界。
关于边界条件的判断可以这么来理解,因为需要搜索的是左边界,而左边界只会出现向右收缩的情况,也就是循环结束后得到的 left
只可能是 >= 0( left 初始条件)
的。
所以出现的越界情况只能是 left === nums.length
,和取不到 target
两种情况。
左闭右开
// 左闭右开
//...
if (nums[mid] === target) {
right = mid; // 只收缩右边界,相当于固定左边界
}
//...
// 边界条件
// target 比所有数都大 或者 取不到 target
if (left === nums.length || nums[left] !== target) {
return -1;
}
// target 在搜索区间的左边
return left;
左闭右闭
// 左闭右闭
//...
if (nums[mid] === target) {
right = mid - 1; // 只收缩右边界,相当于固定左边界
}
//...
// 边界条件
// target 比所有数都大 或者 取不到 target
if (left === nums.length || nums[left] !== target) {
return -1;
}
// target 在搜索区间的左边
return left;
固定右边界,收缩左边界。
关于边界条件的判断可以这么来理解,因为需要搜索的是右边界,而右边界只会出现向左收缩的情况,也就是循环结束后得到的 right
只可能是 <= nums.length(right的一种初始条件)
的。
所以出现的越界情况只能是 right === 0 (或者 -1)
,和取不到 target
两种情况。
左闭右开
// 左闭右开
//...
if (nums[mid] === target) {
left = mid + 1; // 只收缩左边界,相当于固定右边界
}
//...
// 边界条件
// target 比所有数都小 或者 取不到 target
if (right === 0 || nums[right - 1] !== target) {
return -1;
}
// target 在搜索区间的右边
return right - 1;
左闭右闭
// 左闭右闭
//...
if (nums[mid] === target) {
left = mid + 1; // 只收缩左边界,相当于固定右边界
}
//...
// 边界条件
// target 比所有数都小 或者 取不到 target
if (right === -1 || nums[right] !== target) {
return -1;
}
// target 在搜索区间的右边
return right;