笔试题47. LeetCode OJ (34)

来源:互联网 发布:淘宝售后多长时间关闭 编辑:程序博客网 时间:2024/06/05 05:23

 

        找排序数组特定元素的区间,意思是找开始下标和结束下标,但是题目给了要求时间复杂度低于 O(n),这就告诉我们不要使用遍历数组的方式来解题。我们查找单个元素的时候可以二分查找来完成,但是找区间的时候改用什么呢?比如:数组的排列顺序为:5 7 7 8 8 10,而 target = 8 ,我们该怎么找呢?答案还是二分查找,但是思路是这样的:我们先用二分查找找到 target 的大致位置,然后再利用该位置来查找开始下标和结束下标,意思是我们需要使用三次查找,(1)查找mid值,是nums[mid]==target ;

(2).以 left 和 mid去找开始下标;(3).以mid和right去找结束下标;说到这里应该比较明白了吧,但是我还是举个例子来说明吧:

 

上面的是大体上的思路,再注意到一些边界问题该题就可以解决了,代码如下:

class Solution {public:vector<int> searchRange(vector<int>& nums, int target){ //vector<int> ret;ret.clear();int len = nums.size();//非正常情况if (len == 0 || target < nums[0] || target > nums[len - 1]){ret.push_back(-1);ret.push_back(-1);return ret;}int left = 0;int right = len - 1;int mid = 0;//简单的二分查找时不能准确的找到开始和结束点的while (left <= right && nums[left]<=target && nums[right]>=target){//有一边找到了targetmid = left + (right - left) / 2;if (nums[mid] == target){break;}if (nums[mid] < target){left = mid + 1;}else{right = mid - 1;}}        if(nums[left]>target || nums[right]<target)        {            //不合格,最后一起处理        }else if (left == right){if (nums[left] == target){ret.push_back(left);ret.push_back(left);return ret;}else{//没找到,到最后一起处理}}else{ // left < right ,说明nums[mid] == target,那么分别向左找开始点和向右找结束点//左边int lbegin = left;int lend = mid;int lmid = 0;while (nums[lbegin] != target && nums[lbegin + 1] != target){lmid = lbegin + (lend - lbegin) / 2;if (nums[lmid] == target){//说明开始部位可能还在左边lend = lmid;}else{//nums[lmid]<target,此时说明在右边lbegin = lmid;}}            //注意临界条件if (nums[lbegin] == target){ret.push_back(lbegin);}else{ret.push_back(lbegin + 1);}//右边int rbegin = mid;int rend = right;int rmid = 0;while (nums[rend] != target && nums[rend - 1] != target){rmid = rbegin + (rend - rbegin) / 2;if (nums[rmid] == target){//说明结束部位还在右边rbegin = rmid;}else{rend = rmid;}}//注意临界条件if (nums[rend] == target){ret.push_back(rend);}else{ret.push_back(rend - 1);}return ret;}//没找到ret.push_back(-1);ret.push_back(-1);return ret;}};
结果如下:


0 0
原创粉丝点击