1 题目
寻找目标出现的初始位置(First Position of Target)
lintcode:题号——14,难度——easy
2 描述
给定一个排序的整数数组(升序)和一个要查找的整数 target,用O(log n)的时间查找到target第一次出现的下标(从0开始),如果target不存在于数组中,返回-1。
样例:
输入:数组 = [1,4,4,5,7,7,8,9,9,10], target = 4
输出:1
3 思路
从头开始遍历需要的时间复杂度是O(n),要求在O(log n)的时间内完成,可以用二分法解决。
- 找到中间位置的元素;
- 与目标元素比较,确定目标元素所在的区间,缩小目标区间;
- 重复以上操作,直到找到或者结束。
与之前的经典二分搜索1大致相同,可以套用经典二分搜索的模版,需要注意的差异如下:
- 循环中与目标元素的比较在“>”和“==”时候的处理,都是抛掉右边的部分;
- 跳出循环之后,对剩下的两个元素的检查顺序是从左到右。
3.2 图解
3.2 时间复杂度
算法的时间复杂度为O(log n)
3.3 空间复杂度
算法的空间复杂度为O(1)
4 源码
C++版本:
/**
* @param nums: 有序数组
* @param target: 目标元素的值
* @return: 目标元素在有序数组中的初始位置(下标序号)
*/
int binarySearch(vector<int> &nums, int target) {
// write your code here
if (nums.empty())
{
return -1;
}
int start = 0;
int end = nums.size() - 1;
int mid = 0;
while (start + 1 < end)
{
mid = start + (end - start) / 2;
if (nums.at(mid) >= target) // 大于和等于的情况处理方式相同
{
end = mid;
}
else
{
start = mid;
}
}
if (nums.at(start) == target) // 先判断左边的是否是目标元素
{
return start;
}
if (nums.at(end) == target)
{
return end;
}
return -1;
}
5 相同类型问题
题目:
寻找目标出现的最后位置(Last Position of Target)
lintcode:题号——458,难度——easy
C++版本:
/**
* @param nums: 有序数组
* @param target: 目标元素的值
* @return: 目标元素在有序数组中的最后位置(下标序号)
*/
int lastPosition(vector<int> &nums, int target) {
// write your code here
if (nums.empty())
{
return -1;
}
int start = 0;
int end = nums.size() - 1;
int mid = 0;
while (start + 1 < end)
{
mid = start + (end - start) / 2;
if (nums.at(mid) <= target)
{
start = mid;
}
else
{
end = mid;
}
}
if (nums.at(end) == target)
{
return end;
}
if (nums.at(start) == target)
{
return start;
}
return -1;
}
经典二分搜索:https://blog.csdn.net/SeeDoubleU/article/details/118271548 ↩︎