一、今日学习的资源
题目链接:https://leetcode.cn/problems/binary-search/
视频讲解:https://www.bilibili.com/video/BV1fA4y1o715
二、自己看到题目的第一想法
看到题目时,首先注意到两个关键条件:一是升序有序数组,二是必须实现 O (log n) 时间复杂度。第一时间就想到了二分查找算法 —— 因为只有二分查找能在有序数组中以对数级复杂度高效查找,暴力遍历的 O (n) 复杂度完全不符合要求。
看到输入示例nums=[-1,0,3,5,9,12]、target=9,直观判断核心是通过不断缩小查找范围定位目标:先找数组中间元素,和目标值比较后,确定目标在左半区还是右半区,重复这个过程直到找到或确定不存在。
三、自己实现过程中遇到的困难
- mid 计算溢出问题:最初写
mid=(left+right)/2,测试小数组没问题,但想到题目中数组长度最大为 10000,若数组长度更大,left+right可能超出 int 类型范围,导致计算错误。后来改成mid=left+(right-left)/2,才解决了溢出隐患。 - 循环边界条件混淆:一开始写
while(left<right),测试示例 1 时出现错误。仔细分析后才明白,当left==right时,数组只剩一个元素,仍需判断是否为目标值,正确边界应该是while (left<=right)。 - 区间更新逻辑失误:最初写
left=mid或right=mid,导致查找范围无法缩小,陷入死循环。后来明确规则:nums[mid]<target时,目标在右半区,需left=mid+1;nums[mid]>target时,目标在左半区,需right=mid-1,才解决了这个问题。
四、代码实现与测试结果
代码实现
测试结果
五、今日收获心得
- 彻底掌握了二分查找的核心逻辑:有序是前提,对数复杂度是核心,理解了 “每次排除一半元素” 的高效性,也明白这种算法仅适用于有序数组,这是和暴力遍历最本质的区别。
- 学会了关注代码的鲁棒性,比如 mid 计算的防溢出处理,看似是小细节,却能避免严重的运行错误,这在实际开发中非常重要。
- 理清了二分查找的边界细节:循环条件
left <= right、区间更新left = mid + 1和right = mid - 1是固定搭配,理解背后的逻辑后,就不会死记硬背,能灵活应对类似的查找问题。