其实二分法也要用到双指针,首尾;但重点还是基于首尾的中位数进行判断,再不断缩小区间;
1)如力扣34题,在排序数组中查找元素的第一个和最后一个位置;
因为题目已经要求算法的时间负载度控制在O(log n) ,所以自然想到二分法;在找到与target相等的值后,while判断中需要注意索引不要越界;
public static int[] searchRange(int[] nums, int target) {
int l=0,r=nums.length-1,p=0,q=0;
int[] ans = new int[2];
if(nums.length==0){
return new int[]{-1,-1};
}
while (l<=r){
int mid=(l+r)/2;
p=mid;
q=mid;
if(target==nums[mid]){
while (p>=0 && target==nums[p]){
p--;
};
while (q<=nums.length-1 && target==nums[q]){
q++;
};
ans[0]=p+1;
ans[1]=q-1;
return ans;
}
if(target < nums[mid]){
r--;
}else{
l++;
}
}
ans[0]=-1;
ans[1]=-1;
return ans;
}
2)另外有时需要分段判断,判断数据落在哪个有序数组内,如力扣33题和力扣74题;33题需要判断分为在有序区间和不在,最后缩小到最小的有序区间直至数据有无;74题需要判断数据在哪一行,最后缩小到两行,再判断有无;
33题 搜索旋转排序数组
public static int search(int[] nums, int target) {
int l=0,n = nums.length,r=n-1;
while (l<=r){
int mid=(l+r)/2;
if(nums[mid]==target){
return mid;
}
if(nums[0] <= nums[mid]){
if(nums[0]<=target && target<nums[mid]){
r=mid-1;
}else{
l=mid+1;
}
}else{
if(nums[mid]<target && target <=nums[n-1]){
l=mid+1;
}else{
r=mid-1;
}
}
}
return -1;
}
74题 搜索二维矩阵
public static boolean searchMatrix(int[][] matrix, int target) {
int f=0,l=matrix.length-1;
while (f<=l){
if(l-f<=1)break;
int mid=(f+l)/2;
if(target==matrix[mid][0]){
return true;
}
if(target >= matrix[0][0] && target < matrix[mid][0]){
l--;
}else{
f++;
}
}
for (int i : matrix[f]) {
if(i==target)return true;
}
for (int j : matrix[l]) {
if(j==target)return true;
}
return false;
}