加载笔记内容...
加载笔记内容...
二分查找(Binary Search)作为计算机科学中最经典的算法之一,常被开发者视为"简单"算法。但在实际工程实践中,真正能正确实现各种变体并理解其数学本质的开发者不足10%。本文将从基础实现出发,深入探讨其数学原理和工程实践中的关键细节。
1const binarySearch = (nums: number[], target: number) => {
2 let left = 0;
3 let right = nums.length - 1;
4 while (left <= right) {
5 const mid = left + Math.floor((right - left) / 2); // 修正原代码错误
6 if (nums[mid] === target) return mid;
7 if (nums[mid] < target) left = mid + 1;
8 else right = mid - 1;
9 }
10 return -1;
11}
关键点解析:
常见陷阱:
(left + right) / 2
可能溢出,推荐使用 left + (right - left) / 2
1const leftBound = (nums: number[], target: number) => {
2 let left = 0;
3 let right = nums.length;
4 while (left < right) {
5 const mid = left + Math.floor((right - left) / 2);
6 if (nums[mid] >= target) right = mid;
7 else left = mid + 1;
8 }
9 return (nums[left] === target) ? left : -1; // 需要边界检查
10}
工程实践技巧:
1const rightBound = (nums: number[], target: number) => {
2 let left = 0;
3 let right = nums.length;
4 while (left < right) {
5 const mid = left + Math.floor((right - left) / 2);
6 if (nums[mid] <= target) left = mid + 1;
7 else right = mid;
8 }
9 return (left > 0 && nums[left-1] === target) ? left-1 : -1;
10}
数学本质:
left = 第一个大于target的位置
来推导右边界时间复杂度分析:
空间复杂度对比:
工程优化实践:
1function threeSumClosest(nums: number[], target: number): number {
2 nums.sort((a, b) => a - b);
3 let closest = Infinity;
4 for (let i = 0; i < nums.length-2; i++) {
5 let l = i+1, r = nums.length-1;
6 while (l < r) {
7 const sum = nums[i] + nums[l] + nums[r];
8 if (Math.abs(sum - target) < Math.abs(closest - target))
9 closest = sum;
10 sum > target ? r-- : l++;
11 }
12 }
13 return closest;
14}
算法分析:
关键优化点:
常见问题集锦:
问题现象 | 可能原因 | 解决方案 |
---|---|---|
死循环 | 边界更新错误 | 检查循环条件和mid计算 |
越界访问 | 未验证最终索引 | 添加边界条件检查 |
漏解 | 区间定义错误 | 明确循环不变量 |
调试方法论:
最新研究方向:
工业界应用案例:
1// 测试用例示例
2const testCases = [
3 { input: [[], 0], expected: -1 },
4 { input: [[1], 1], expected: 0 },
5 { input: [[2,2], 2], expected: 0 }, // 左边界检查
6 { input: [[1,2,3,4,4,4,5], 4], expected: 3 } // 右边界检查
7];
旋转数组搜索:如何在O(log n)时间内搜索旋转排序数组?
1function searchRotated(nums, target) {
2 let l = 0, r = nums.length-1;
3 while (l <= r) {
4 const mid = (l + r) >> 1;
5 if (nums[mid] === target) return mid;
6 // 判断哪半边是有序的
7 if (nums[l] <= nums[mid]) { // 左半有序
8 if (nums[l] <= target && target < nums[mid]) r = mid-1;
9 else l = mid+1;
10 } else { // 右半有序
11 if (nums[mid] < target && target <= nums[r]) l = mid+1;
12 else r = mid-1;
13 }
14 }
15 return -1;
16}
二分答案法:将最优化问题转化为判定问题
三维空间最近点搜索:将双指针扩展到三维场景
通过深入理解二分查找的数学本质,开发者可以将其应用于更广泛的工程场景。记住:优秀的算法工程师与普通开发者的区别,往往体现在对边界条件的处理和对算法本质的理解深度上。