题目描述:
给定一个排序的整数数组(升序)和一个要查找的整数target,用O(logn)的时间查找到target第一次出现的下标(从0开始),如果target不存在于数组中,返回-1。
例如:在数组 [1, 2, 3, 3, 4, 5, 10] 中二分查找3,返回2。
思路:
首先比较中间的数和要查找的数,如果关键字(要查找的数)小于中间的数,那么在数组的左半部分继续查找,如果关键字大于中间的数,那么在数组的右半部分继续查找,如果关键字和中间的数相等,那么比较中间数字的前一个数字是否和关键字相等,如果不相等,那么当前的中间索引就是第一次出现的索引,如果相等,那么继续在前半部分查找。
代码1(数组方式):
int GetFirstTarget(int arr[],int k,int start,int end)
{
if (start > end)
{
return -1;
}
//中间索引
int mid = start + ( (end-start) >> 1);
int midData = arr[mid];
while (start <= end)
{
if (k > midData)
{
start = mid+1;
}
else if (k < midData)
{
end = mid-1;
}
else if (k == midData)
{
if ((k != arr[mid-1] && mid > 0) || mid == 0)
{
return mid;
}
else
end = mid-1;
}
//更新中间值的索引和值
mid = start + ( (end-start) >> 1);
midData = arr[mid];
}
return -1;
}
代码2(向量方式):
int GetFirstTarget(vector<int> &arr,int k)
{
if(arr.size() == 0)
{
return -1;
}
int start = 0;
int end = arr.size() - 1;
int mid;
while (start + 1 < end)
{
mid = start + (end - start) / 2;
if (arr[mid] == k)
{
end = mid;
}
else if (arr[mid] < k)
{
start = mid;
}
else if (arr[mid] > k)
{
end = mid;
}
}
if (arr[start] == k)
{
return start;
}
if (arr[end] == k)
{
return end;
}
return -1;
}
拓展:寻找最后一次出现的索引
int GetLastTarget(int arr[],int len, int k,int start,int end)
{
if (start > end)
{
return -1;
}
//中间索引
int mid = start + ( (end-start) >> 1);
int midData = arr[mid];
while (start <= end)
{
if (k > midData)
{
start = mid+1;
}
else if (k < midData)
{
end = mid-1;
}
else if (k == midData)
{
if ((k != arr[mid+1] && mid < 0) || mid == len - 1)
{
return mid;
}
else
end = mid + 1;
}
//更新中间值的索引和值
mid = start + ( (end-start) >> 1);
midData = arr[mid];
}
return -1;
}
ps:完整测试程序请看我的代码片:binarySearch.cpp