二分查找问题
- 问题1:如何在lgn的时间内,查找有序数据中的特定元素?
- 关键点:有序数组 + 查找问题
- 核心思想: 分治思想,时间复杂度O(lgn)
- 具体步骤:从有序数组中间开始查找,判断当前元素是大于还是小于目标元素,然后缩小查找范围为左区间或者右区间,继续循环以上步骤。
相关题目 704. Binary Search
public int search(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = (right - left) / 2 + left;
int num = nums[mid];
if (num == target) {
return mid;
} else if (num > target) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return -1;
}
- 注意点:
- 计算mid 时不要用 mid = (right + left) /2; 这样容易溢出,正确写法
int mid = (right - left) / 2 + left;
- 注意right 的取值和while条件的边界判断
变式
- 问题2: 如果问题1的有序数组内有重复元素,那么如何查找特定元素target第一次出现或者最后一次出现的位置?
- 区别: 这里涉及到了一个范围,即找到 >= target的元素区间的起始位置
- 算法代码:
int search(int[] nums, int target){
int n = nums.length;
int left = 0, right = n ;
int mid = 0;
while(left < right){
mid = left + (right - left)/2;
//因为不确定此时mid指向的元素是不是第一个大于等于target的元素,所以right = mid, 而不是right= mid -1 , 如果是后者的写法,就把该元素错过了
if(nums[mid] >= target){
right = mid;
}else{
left = mid + 1;
}
}
//返回right 或者left 都一样, 如果未找到,则返回n
return right;
}
-
注意点:
- right = nums.length, 且 判断条件时left < right
-
相关题目
-
lc 34. Find First and Last Position of Element in Sorted Array
- 题目要求:是在非降序数组内查找目标元素target出现的第一个和最后一个位置
- 核心思想:就是复用两次上面的模板:找到大于等于target 的元素起始位置,以及找到大于等于target + 1的元素起始位置
-
lc 2529. Maximum Count of Positive Integer and Negative Integer 也是同理,思路一致。
-