力扣-34-在排序数组中查找元素的第一个和最后一个位置

传送门

这个题从时间复杂度来看要用二分搜索,但是不同于力扣-33题,那道题中目标数字是不重复的,这道题需要同时输出查找元素的第一个和最后一个位置。

方法一:使用STL自带的函数

#include <algorithm>
class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int n = nums.size();
        if (n==0) return {-1, -1};
        if (!binary_search(nums.begin(), nums.end(), target)) return {-1, -1};
        int res1 = lower_bound(nums.begin(), nums.end(), target) - nums.begin();
        int res2 = upper_bound(nums.begin(), nums.end(), target) - nums.begin();
        vector<int> res;
        res.push_back(res1);
        res.push_back(res2 - 1);
        return res;
    }
};
代码
  • lower_bound(start, end, target):返回第一个大于等于查找元素的地址。
  • upper_bound(start, end, target):返回第一个大于查找元素的地址。
  • binary_search(start, end, target):判断查找元素是否存在[start, end)这个区间中,返回布尔值True/False

STL中的提供了三个算法,时间复杂度都是O(logn)

lower_bound和upper_bound返回的都是查找元素的地址,要想知道其在数组中的下标,还要减去首地址,如下

        int res1 = lower_bound(nums.begin(), nums.end(), target) - nums.begin();
        int res2 = upper_bound(nums.begin(), nums.end(), target) - nums.begin();

这样就可以用res1表示查找元素的第一个位置,用(res2-1)表示查找元素的最后一个位置,前提是存在哈。

方法二:用二分搜索即可

①、输出第一个位置

          int l = 0, r = n - 1;
          while(l < r){   
            int mid = l + (r - l)/2;  /*mid这里向下取整*/
            if (nums[mid] >= target){
                r = mid;
            }
            else{
                l = mid + 1;
            }
        }
         return l; /*return l还是r都可以,因为循环终止条件是l==r*/

②、输出第二个位置

        l = 0, r = n - 1;
        while(l < r){
            int mid = l + (r - l + 1)>>1;   /*向上取整*/
            if (nums[mid] <= target){
                l = mid;
            }
            else{
                r = mid - 1;
            }
        }
         return r; /*return l还是r都可以*/
#include <algorithm>
class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int n = nums.size();
        if (!n) return {-1, -1};    /*when vector's length = 0*/
        int l = 0, r = n - 1;
        while(l < r){   /*if l == r ,then return left or right both ok*/
            int mid = l + (r - l)/2; /*floor mid*/
            if (nums[mid] >= target){
                r = mid;
            }
            else{
                l = mid + 1;
            }
        }
        if (nums[l] != target) return {-1, -1}; /*Not found*/
        int res_1 = l;
        l = 0, r = n - 1;
        while(l < r){
            int mid = l + (r - l + 1)/2;   /*ceil mid*/
            if (nums[mid] <= target){
                l = mid;
            }
            else{
                r = mid - 1;
            }
        }
        if (nums[r] != target) return {-1, -1};
        int res_2 = r;
        return {res_1 ,res_2};
    }
};
代码

 图示

posted @ 2020-07-10 19:06  Peterxiazhen  阅读(229)  评论(0编辑  收藏  举报