[offer_53-1] 在排序数组中查找数字 I (开启编辑看 i,j,m)
题目
思路
我们要统计一个数字在排序数组中出现的次数,那么则可以找到该数字的左边界和右边界,例如 1,3,3,4 找3
那我们可以找到1和4,则3的个数则为3-0-1,让1的下标为左边界left,4的下标为右边界right。则count = right - left - 1
1 3 3 4 (二分查找)先找左边界 while i <= j
i m j (m>=target) j = m - 1
i,m,j 均指向1 i = m + 1
j,m i
则left == j == 0 但是如果left == len-1 || nums【left+1】!=target 就可以判断无此数了
1 3 3 4 二分查找 找右边界 while i<=j
i m j m<=target i=m+1
i,m j i=m+1
ijm m>target 则j = m-1 break
right = i (ps:此时一定有target)
所以返回 right-left-1
代码
/**
* 官方题解 找左边和右边的
*/
public class Solution {
public int search(int[] nums, int target) {
if (nums == null || nums.length == 0)
return 0;
int i = 0;
int j = nums.length - 1;
while (i <= j){
int mid = (i + j) / 2;
if (nums[mid] < target)
i = mid + 1;
else
j = mid - 1;
}
int leftIndex = j;
if (leftIndex + 1 >= nums.length || nums[leftIndex + 1] != target) //2222 找 3
return 0;
i = 0;
j = nums.length - 1;
while (i <= j){
int mid = (i + j) / 2;
if (nums[mid] <= target)
i = mid + 1;
else
j = mid - 1;
}
int rightIndex = i;
return rightIndex - leftIndex - 1;
}
}
思路二
从思路1可以发现 找left就是找的比target小的第一个数的下标
那么由此可以改进找比target+1小的第一个数的第一个下标
如若有,则正好 如22222 找2 left = -1 找3 left=4
122223 找2 left 0 找3则left=4 那么我们可以找target的left 和target+1的left 就想到于有坐标就是找到target的最右边
代码
public class Solution1 {
public static int search(int[] nums, int target) {
if (nums == null || nums.length == 0)
return 0;
return searchLeft(nums,target + 1) -searchLeft(nums,target);
}
public static int searchLeft(int[] nums, int target){
int i = 0;
int j = nums.length - 1;
while (i <= j){
int mid = (i + j) / 2;
if (nums[mid] < target)
i = mid + 1;
else
j = mid - 1;
}
int leftIndex = j;
return leftIndex;
}
}