leetcode704-二分查找
2024-02-18 本文已影响0人
巡山的小猴子
这个题思路很简单,而且酒桌上也总玩,也想出坑害别人的办法(就剩下两个数字给下家,那么就是最后两个人喝酒了)哈哈哈
但是真正做这个题,边界很不好考虑
class Solution {
public int search(int[] nums, int target) {
int left = 0;
int right = nums.length -1;
while(left <= right){
int mid = left + ((right - left) / 2);
if (target > nums[mid]){
left = mid +1;
}else if(target < nums[mid]){
right = mid - 1;
}
if(target == nums[mid]){
return mid;
}
}
return -1;
}
}
- while(left <= right) 循环这么写,写上等号,因为要考虑mid 等于left,或者right的情况,没有等号可能导致找不到
- left + ((right - left) / 2) 替代(right + left) / 2 防止数组太大了,int 溢出了
- left = mid +1,right = mid - 1 这个主动缩小范围的+1,-1 不能省略,原来觉得不就是扩大了范围,多迭代一两次么。其实是,如果不缩小范围,就会导致死循环,特别是当mid恰好等于left或right时,这种调整方式不会改变搜索范围,因为在下一次迭代中mid将会再次计算为相同的值,从而导致循环不会停止。
举例说明:
用例是nums2 = {-1, 0, 3, 5, 9, 12},目标值target2 = 2。
初始条件:
left = 0
right = 5 (因为数组长度为6)
第一次迭代:
mid = 0 + (5 - 0) / 2 = 2(使用整数除法,结果向下取整)
nums2[mid] = 3
由于3 > 2,按照新的调整方式,right = mid = 2
第二次迭代:
left = 0
right = 2
mid = 0 + (2 - 0) / 2 = 1
nums2[mid] = 0
由于0 < 2,按照新的调整方式,left = mid = 1
第三次迭代:
left = 1
right = 2
mid = 1 + (2 - 1) / 2 = 1(因为使用整数除法,结果向下取整)
nums2[mid] = 0
由于0 < 2,按照新的调整方式,left = mid = 1
可以看出,从第三次迭代开始,left、mid、right的值不再发生变化,因为left和mid都被重复设置为1,而right保持在2。这导致算法陷入了死循环,因为它不再能够递进地缩小搜索范围。
这个例子展示了为什么使用left = mid;和right = mid;这种调整方式可能会导致算法无法正确前进,特别是在目标值不存在于数组中时。正确的做法应该是在目标值大于mid值时让left等于mid + 1,在目标值小于mid值时让right等于mid - 1,这样可以保证每一次迭代都能有效缩小搜索范围,最终避免死循环。