只讲几个边界的注意点
问题:
看下面这这两段代码
左闭右闭
int left = 0;
int right = nums.length - 1;
while (left <= right){
//找到了返回
if(nums[middle] < target){
left=middle+1;
}else if(nums[middle] > target){
right = middle -1;
}
左闭右开
int left = 0;
int right = nums.length;
while (left <= right){
//找到了返回
if(nums[middle] < target){
left=middle+1;
}else if(nums[middle] > target){
right = middle;
}
解释:
1.什么叫左闭右闭?左闭右开?
- 左闭 :表示左边的边界是包含在内的 ,也就是说,
left
这个位置是可以被考虑的。 - 右开 :表示右边的边界是不包含在内的 ,也就是说,
right
这个位置是不能被考虑的 。
eg.
[-1,0,3,5,9,12]
左闭右闭:搜索范围是-1到12。
左闭右开:搜索范围是-1到9,12不在考虑范围 。
2.代码解释
左闭右闭
int left = 0;
int right = nums.length - 1;
/*
为什么这里是 left <= right
因为你的搜索范围是 [0~nums.length - 1],
也就说我每一个值都要考虑,
如果是 < 且 搜索范围是 [0~nums.length - 1],
那么一定就会搜索范围就会比[0~nums.length - 1]小,
因为 left < right,就会少left=rigth的值。
*/
while (left <= right){
//找到了返回
if(nums[middle] < target){
/*
这里为什么是 left = middle+1 而不是 left=middle;
因为,你的搜索范围是[0~nums.length - 1]也就说数组每一个值都可以取到
而你 nums[middle] < target条件成立,也就意味着你此时nums[middle]一定不等于target
所以只需要left=middle+1 进行下一个值
right = middle -1同理
*/
left=middle+1;
}else if(nums[middle] > target){
right = middle -1;
}
左闭右开
int left = 0;
int right = nums.length;
/*
为什么这里是 left < right,
因为你的搜索范围是 [0~nums.length],
eg.[-1,0,3,5,9,12]
length=6
nums[5]=12;
所以,会取到12后面还有一个值,但是取不到这个值,会报索引异常。
所以,这里要求是left<right 也就说right这个位置不可以取到,
取到会报索引异常。
*/
while (left < right){
//找到了返回
if(nums[middle] < target){
/*
为什么这里是 left=middle+1;而不 left=middle;
因为这里搜索范围是左闭右开,
也就意味着你左边的值,nums[middle] < target 这个判断成立时,
nums[middle]一定不等于target,
进行+1找下一个值即可。
*/
left=middle+1;
}else if(nums[middle] > target){
/*
为什么这里是 right = middle;而不是 right = middle+1;
因为这里搜索范围是左闭右开,意味着
nums[middle] > target 这个成立时,
target一定在middle左边的区域,
而我们的搜索范围是[left,right),取不到right
所以可以直接right = middle;
[left,right) == [left,right-1]
*/
right = middle;
}
总结
1.搞清楚到底用哪个边界,是左闭右闭,还是左闭右开。
2.确定好边界范围,只要思考我的搜索范围能不能这个值,就可以写对。