s1-数组-3

85 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情

s1-数组-3

力扣34

#1.题目

image-20220609184733110

#2.题目解析

这个题目其实就是二分的升级版

我们对待这个题目的具体思路就是我们首先通过一个二分来找到我们数组的右边界,然后再来一个二分找到我们的左边界

我们分析一个就可以,我们分析找右边界(右边界看左指针)

寻找右边界的函数

 int findRight(vector<int> &nums, int target)
     {
         int left = 0;
         int right = nums.size() - 1;
         int Right = -2; //定义我们的右边界
         while (left <= right)
         {
             //这里我们的处理逻辑其实还是我们二分那一套
             int mid = left + ((right - left) / 2);
             if (nums[mid] > target)
             {
                 right = mid - 1;
             }
             else //这里我们的处理其实还是很有意思的,这里我们把nums[mid]<target以及==的情况下我们都集合到了一起,其实核心就是当nums[mid]==target时我们也要让left继续前进直到不包括我们的目标值为止
             {
                 left = mid + 1;
                 Right = left;
             }
         }
         return Right;
     }

我们看下这里面的二分

  while (left <= right)
         {
             //这里我们的处理逻辑其实还是我们二分那一套
             int mid = left + ((right - left) / 2);
             if (nums[mid] > target)
             {
                 right = mid - 1;
             }
             else //这里我们的处理其实还是很有意思的,这里我们把nums[mid]<target以及相等的情况下我们都集合到了一起,其实核心就是当nums[mid]==target时我们也要让left继续前进直到不包括我们的目标值为止
             {
                 left = mid + 1;
                 Right = left;
             }
         }

我们就算是和目标值相等我们也要继续前进,我们取得的边界是不包含目标值的边界

接下来我们上一个实例,在下列数组中查找5的边界

image-20220609190301278

大家对照着这个图好好思考下

同理我们给出求左边界的代码(左边界要看右指针)

 int findLeft(vector<int> &nums, int target)
     {
         int left = 0;
         int right = nums.size() - 1;
         int Left = -2;
         while (left <= right)
         {
             int mid = left + ((right - left) / 2);
             if (nums[mid] >= target) //要在nums[mid]==target的时候继续让right--
             {
                 right = mid - 1;
                 Left = right;
             }
             else
             {
                 left = mid + 1;
             }
         }
         return Left;
     }

接下来我们考虑下我们可能会出现的几种情况

  • 情况一:target 在数组范围的右边或者左边,例如数组{3, 4, 5},target为2或者数组{3, 4, 5},target为6,此时应该返回{-1, -1}
  • 情况二:target 在数组范围中,且数组中不存在target,例如数组{3,6,7},target为5,此时应该返回{-1, -1}
  • 情况三:target 在数组范围中,且数组中存在target,例如数组{3,6,7},target为6,此时应该返回{1, 1}

#3.上代码

 class Solution
 {
 public:
     vector<int> searchRange(vector<int> &nums, int target)
     {
         int R = findRight(nums, target);
         int L = findLeft(nums, target);
         if (R == -2 || L == -2) //说明此时的已经找不到我们的目标区间了
         {
             return {-1, -1};
         }
         //我们的正常情况
         if (R - L > 1) //因为我们的左右边界都是没有包含我们那个目标值,所以这里我们最起码间隔一
         {
             return {L + 1, R - 1};
         }
         //除此之外的情况的应对措施
         return {-1, -1};
     }
 ​
 private:
     int findRight(vector<int> &nums, int target)
     {
         int left = 0;
         int right = nums.size() - 1;
         int Right = -2; //定义我们的右边界
         while (left <= right)
         {
             //这里我们的处理逻辑其实还是我们二分那一套
             int mid = left + ((right - left) / 2);
             if (nums[mid] > target)
             {
                 right = mid - 1;
             }
             else //这里我们的处理其实还是很有意思的,这里我们把nums[mid]<target以及相等的情况下我们都集合到了一起,其实核心就是当nums[mid]==target时我们也要让left继续前进直到不包括我们的目标值为止
             {
                 left = mid + 1;
                 Right = left;
             }
         }
         return Right;
     }
     int findLeft(vector<int> &nums, int target)
     {
         int left = 0;
         int right = nums.size() - 1;
         int Left = -2;
         while (left <= right)
         {
             int mid = left + ((right - left) / 2);
             if (nums[mid] >= target) //要在nums[mid]==target的时候继续让right--
             {
                 right = mid - 1;
                 Left = right;
             }
             else
             {
                 left = mid + 1;
             }
         }
         return Left;
     }
 };

\