题目:leetcode34
这题目言简意赅,看标题就可以了,就是找出一个数字在数组中出现的第一个和最后一个位置。
第一想法暴力。然后看要求时间复杂度O(logn),不说了,二分。不能二分就是不会。再看题目ascending order(ascend:上升),这就一有序的数组嘛,符合二分的条件。move hand。
知道用哪种方法,那怎么做呢?先讨论简单的情况,当nums[mid] ≠ target时,咱们直接选一边递归就可以了。麻烦的是当nums[mid] = target时。讨论一下
1.如果first和last下标都是-1,说明在此之前没有找到这个数。那么现在我们找到了就需要更新first和last为mid。
2.不然的话,我们只需要把first和mid,last与mid进行比较,然后替换就可以了。
注:其实开始写的很复杂,考虑了first = -1,last ≠ -1的情况,但分析发现,由于第一次找到mid时会同时更新两个的值,所以它们要么都是-1,要么都不是-1。
但是,这就完了吗?考虑nums为8,8,8;target=8的样例,当我们nums[mid]刚好为target时就不用再找找了吗?肯定不是啊,还要往两边去找,去更新两者。
有了大概的逻辑,代码实现就简单起来。直接上代码吧:
class Solution {
public:
vector<int>ans;
void binarySearch(vector<int>& nums, int target, int low, int high) {
if (low > high) return; //记得跳出循环哦。
int mid = (low + high) >> 1;
if (nums[mid] == target) { // 中间值为target的情况哦。
if (ans[0] == -1 && ans[1] == -1) ans[0] = ans[1] = mid;
else {
if (ans[0] > mid) ans[0] = mid;
if (ans[1] < mid) ans[1] = mid;
}
/*千万别停止搜索,给我接着搜*/
binarySearch(nums, target, low, mid - 1);
binarySearch(nums, target, mid + 1, high);
}
/*中间不是就可以找一边了,中间是要找两边哦*/
else if (nums[mid] > target) binarySearch(nums, target, low, mid - 1);
else binarySearch(nums, target, mid + 1, high);
return;
}
vector<int> searchRange(vector<int>& nums, int target) {
ans = { -1,-1 };
if (nums.size() == 0 || nums[0] > target || nums[nums.size() - 1] < target)
return { -1,-1 };
binarySearch(nums, target, 0, nums.size() - 1);
return ans;
}
};
这这这就完了吗?等一下,回顾一下与二分有关的函数。对了!不是有lower_bound()和upper_bound()函数吗?动手!
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
vector<int> ans = { -1,-1 };
if (nums.size() == 0 || nums[0] > target || nums[nums.size() - 1] < target
|| binary_search(nums.begin(), nums.end(), target) == 0)
return { -1,-1 };
ans[0] = lower_bound(nums.begin(), nums.end(), target) - nums.begin();
ans[1] = upper_bound(nums.begin(), nums.end(), target) - nums.begin() - 1;
return ans;
}
};
这里简单说一下吧,low_bound(起始地址,结束地址,val)
作用:返回>=val的第一个地址。
upper_bound(起始地址,结束地址,val)
作用:返回>val的第一个地址。
那么这道题就搞定了,感谢你们看到这,也感谢我自己写到这。哈哈哈,表述不清的地方欢迎交流哦!