1、二分查找的前提条件
- 数组有序
- 数组中没有重复元素;否则会导致结果下标不唯一
2、两种写法
1、左闭右闭区间[left,right]
有两个需要注意第地方
- 循环条件
while (left<=right)
因为是左闭右闭,所以left=right是有意义的 - 当
nums[mid]>target
时,mid赋值为right-1
因为当前的nums[mid]一定不是target,那么查找的区间就是right-1
class Solution {
public int search(int[] nums, int target) {
//1、左闭右闭区间
int left = 0;
int right = nums.length - 1;
//注意点1:<= 因为是左闭右闭区间,所以left=right是有意义的
while (left <= right) {
//防止发生溢出:当left不断增大,达到极限状态也就时=right-1时,
//如果数组的长度刚好很大,那么可能会导致溢出出现负数
//int mid1 = (left + right) / 2;
int mid = left + ((right - left) / 2);
//注意点2:right=mid-1 因为nums[mid]一定不是target
if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
} else {
return mid;
}
}
return -1;
}
}
2、左闭右开区间[left,right)
也有两个地方需要注意
- 循环条件为
while(left<right)
因为为开区间,所以left=right没有意义 - 当
nums[mid]>target
时,right赋值为mid
nums[mid]>target的话,需要去左区间继续搜寻,寻找区间是左闭右开的,所以right=mid,让区间变为[left,mid),mid不用再去比较
class Solution {
public int search(int[] nums, int target) {
//1、左闭右开
int left = 0;
int right = nums.length;
//注意点1:< 因为是左闭右开区间,所以left=right是没有意义的
while (left < right) {
//防止发生溢出:当left不断增大,达到极限状态也就时=right-1时,
//如果数组的长度刚好很大,那么可能会导致溢出出现负数
//int mid1 = (left + right) / 2;
int mid = left + ((right - left) / 2);
//注意点2:right=mid,不相等需要从左边区间再去搜寻,左闭右开的区间,
//让right=mid,就不用再比较nums[mid]了
if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid;
} else {
return mid;
}
}
return -1;
}
}
3、时间复杂度和空间复杂度
- 时间复杂度为O(log n)
- 空间复杂度为O(1)