题目描述:
题目:
给你一个按照非递减顺序排列的整数数组 nums
,和一个目标值 target
。请你找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target
,返回 [-1, -1]
。
你必须设计并实现时间复杂度为 O(log n)
的算法解决此问题。
示例:
示例 1:
输入:nums = [5,7,7,8,8,10], target = 8 输出:[3,4]
示例 2:
输入:nums = [5,7,7,8,8,10], target = 6 输出:[-1,-1]
示例 3:
输入:nums = [], target = 0 输出:[-1,-1]
解题思路:
为什么要用二分法?
题目中有几个关键词:非递减的数组、查找元素在数组的位置、时间复杂度为o(log n)。这些都是使用二分法的暗示。
这道题难点在哪?
既然已经知道要用二分法解题,那么就可以开始思考难点啦。我觉得二分法不难,难的是如何把二分法灵活运用起来。这道题的难点就在于如何通过二分法找到给定元素首尾位置,由于本人水平有限,这里只给出一种解题思路,读者有其他想法欢迎讨论、赐教~
破题思路是什么?
这道题可以分成三个部分:寻找元素第一次出现的位置、寻找最后一次出现的位置、元素没有出现时的算法调整。
寻找位置的关键:根据二分法,当中间值大于目标值,右边界(right)应该被赋与mid - 1;当中间值小于目标值,左边界(left)应该被赋予mid + 1;当中间值等于目标值就可以退出循环了。这道题巧妙之处在于找到和目标值相同的元素时不退出循环,而是将其根据此次循环中右边界(right)和左边界(left)的变化情况记录下来,如果是right变化了,得到的就是首位置,反之就是尾位置。
1.寻找元素第一次出现的位置
注意:第14、15行代码不可以颠倒顺序,因为是先寻找变化的边界,待其变化完成之后再记录其值,下同。
2.寻找最后一次出现的位置
3.元素没有出现时的算法调整
元素没有出现的情况有以下两种:
不在范围内。如 {5,7,7,8,8,10} 中寻找数字 2 ,或寻找数字 11
在范围内。如 {5,7,7,8,8,10} 中寻找数字 6
对于第一种情况,在调用功能函数时一直没有执行“更新首尾位置变量”的代码,返回值仍为初始值 -2,所以直接判断返回值是否为 -2 即可。
除第二种情况之外,其余情况判断完之后,如果程序还没返回,就说明元素在范围内但没有出现,此时返回 {-1,-1} 即可。
代码:
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
int left = getLeftBorder(nums, target); //获得首位置
int right = getrightBorder(nums, target); //获得尾位置
if (left == -2 || right == -2) return { -1, -1 }; //元素未出现的第一种情况
if (right - left > 1) return { left + 1, right - 1 }; //元素出现
return { -1, -1 }; //元素未出现的第二种情况
}
int getLeftBorder(vector<int>& nums, int target) {
int left = 0; //左边界
int right = nums.size() - 1; //右边界
int leftborder = -2; //记录首位置值
while (left <= right) {
int mid = (left + right) / 2;
if (nums[mid] >= target) { //如果中间值 >= target,更新并记录right值
right = mid - 1;
leftborder = right;
}
else left = mid + 1;
}
return leftborder; //返回首位置
}
int getrightBorder(vector<int>& nums, int target) {
int left = 0;
int right = nums.size() - 1;
int rightborder = -2;
while (left <= right) {
int mid = (left + right) / 2;
if (nums[mid] <= target) { //如果中间值 <= target,更新并记录left值
left = mid + 1;
rightborder = left;
}
else right = mid - 1;
}
return rightborder;
}
};
我是左岸花花 感谢阅读我的博客~ 因为有你,这个冬天不再寒冷^_^