目录
1. 题目描述
已知一个从小到大的排序数组,求数组中等于目标值元素的下标,数组中可能有重复的元素,所以如果目标值存在,返回目标值在数组中的开始位置和结束位置,如果目标值不存在,返回两个-1。
2. 题目分析
这一题是典型的二分查找,需要用到两次,分别查找目标值开始位置和结束位置
(1)第一次查找 (起始位置)
起始位置二分查找代码的实现,传入数组nums与目标值target
函数返回数组中第一个等于目标值的元素下标
设置搜索区间左端点为0,右端点为数组长度减1
左端点小于等于右端点时,进行二分查找
mid=(left+right)/2
(1)如果中间元素等于目标元素(mid为数组的第一个元素或mid的前一个元素小于target) 这时mid指向了mid的起始位置,将它返回。否则设置right等于mid减1
(2)如果中间元素大于target,设置right等于mid减1
(3)如果中间元素小于target,设置left等于mid加1
当循环结束后没有返回,则说明数组中没有目标元素,返回-1
我们来结合一道例题进行讲解
(1)我们先设置区间的左右端点 ,并利用mid=(0+9)/2=4来确定mid
(2)比较mid所指元素与目标值大小,此时都为7 ,他的前一个元素不小于(大于等于)7,所以起始位置在mid的左侧,将搜素区间的右端点right设置为mid-1。我在假设一下另外一种情况(和这一题没什么关系)如果mid此时指向元素为6,6<7,这时候要将left设置为mid+1
(3)mid=(0+3)/2=1 ,将mid置于1
(4)此时mid所指元素为6,6<7,设置left=mid+1
(5)mid=(2+3)/2=2,将mid置于2
(6)此时mid所指元素为6,6<7,设置left=mid+1
(7)mid=(2+3)/2=2,将mid置于3,循环结束
(2)第二次查找(结束位置)
与第一次查找类似
3.核心代码
public class Solution {
public int Search(int[] nums, int target) {
int low = 0, high = nums.Length - 1;
while (low <= high) {
int mid = (high - low) / 2 + low;
int num = nums[mid];
if (num == target) {
return mid;
} else if (num > target) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return -1;
}
}