【算法练习】二分搜索/旋转数组系列题目

题目

33. 搜索旋转排序数组

81. 搜索旋转排序数组 II

153. 寻找旋转排序数组中的最小值

154. 寻找旋转排序数组中的最小值 II

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

 

思路

参考题解 主要参考的三叶姐的题解以及其他几个题解的延伸

https://leetcode-cn.com/problems/search-in-rotated-sorted-array-ii/solution/gong-shui-san-xie-xiang-jie-wei-he-yuan-xtam4/

二分搜索练习参考

https://leetcode-cn.com/problems/search-insert-position/solution/te-bie-hao-yong-de-er-fen-cha-fa-fa-mo-ban-python-/

 

搜索旋转排序数组 1、2

33. 搜索旋转排序数组

81. 搜索旋转排序数组 II

容易理解的思路是根据 旋转排序数组的二段性,画图可知

主要思路:

1、(有重复元素先恢复二段性)找到二段性分割点 也就是找到满足>=nums[0]的最大值
2、此时right就是分割点的index 判断target到底在哪边进行二分查找

代码1

 

代码2

 

153. 寻找旋转排序数组中的最小值

方法一、与nums[right]比较

代码

 int findMin(vector<int>& nums) {
    int n=nums.size();
    int left=0,right=n-1;
    //画图理解二分性
    while(left<right){
        int mid=left+(right-left)/2;
        //只有1个数字的时候nums[mid]==nums[right] 此时已经退出
        if(nums[mid]>nums[right]){
            //说明min在mid右侧
            left=mid+1;
        }else if(nums[mid]<nums[right]){
            //说明min在mid左侧 或者就是min
            right=mid;
        }
    }
    return nums[left];
}

 

方法二、与nums[0]比较  找到旋转点 根据旋转点返回最小值

int findMin(vector<int>& nums) {
    int n=nums.size();
    int left=0,right=n-1;
    //找到>=nums[0]的最大的值
    while(left<right){
      int mid=left+right+1>>1;
      if(nums[mid]>=nums[0]){
          left=mid;
      }else{
          right=mid-1;
      }
    }
    return nums[(right+1)%n];
}

 

154. 寻找旋转排序数组中的最小值 II

方法一、先恢复二段性 然后找到旋转点 最后得到最小值

int findMin(vector<int>& nums) {
    //恢复二段性
    int n=nums.size();
    int left=0,right=n-1;
    while(left<right && nums[right]==nums[0]){
        right--;
    }
    //得到了新的right  恢复了二段性
    //找到旋转点
    while (left<right){
        int mid=left+right+1>>1;
        if(nums[mid]>=nums[0]){
            left=mid;
        } else{
            right=mid-1;
        }
    }
    return nums[(right+1)%n];
}

方法二、类似上一题的思路,

尝试先恢复二段性 然后利用与nums[right]的关系找到最小值

int findMin(vector<int>& nums) {
    //恢复二段性
    int n=nums.size();
    int left=0,right=n-1;
    while(left<right && nums[right]==nums[0]){
        right--;
    }
    //得到了新的right  恢复了二段性
    //根据和nums[right]二分搜索
    while (left<right){
        int mid=left+(right-left)/2;
        if(nums[mid]>nums[right]){
            left=mid+1;
        }else{
            right=mid;
        }
    }
    return nums[right];
}

 

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

关于二分搜索的细节问题

nums[mid]<=target 符合条件的就是前面的一段

然后我们最终找到的必然是这一段的右端点(因为它相对于左端点 必然更接近中心) 也就是最后一个 8

而有没有 +1 取决于 我们在 check 条件为 true 的时候 修改的是不是 left 指针 如果是的话 就要 + 1

这是为了防止下取整导致的死循环

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值