LeetCode:33 搜索旋转排序数组 递归+二分

假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。

搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。

你可以假设数组中不存在重复的元素。
你的算法时间复杂度必须是 O(log n) 级别。

示例 1:
输入: nums = [4,5,6,7,0,1,2], target = 0
输出: 4

示例 2:
输入: nums = [4,5,6,7,0,1,2], target = 3
输出: -1

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

这个题需要用到递归,对于一个旋转过后的排序数组,从中间分开,至少有一半是有序的,对于左右两个序列,通过判断左端点和右端点值的关系,可以确定其是否有序

  1. 对有序的部分,如果目标在上下界之间,二分搜索目标
  2. 如果不在范围内,表示值在无序的那边,对无序序列递归,继续将无序部分划分为有序+无序,继续搜索

递归思路

对于旋转过的排序数组,我们将他一分为三:

左边一坨,中间元素,右边一坨
  1. 判断中间元素是否等于目标,如果等于,就返回

  2. 如果左边有序,右边无序:

    如果目标位于左序列上下界之间,对该序列二分搜索
    如果没搜到,返回-1,因为在确定范围内未找到元素

    如果目标不在上下界之间,对右边无序序列递归地划分为 有序+无序,转1

  3. 如果左边无序,右边有序:(执行2中的镜像操作)

    如果目标位于右序列上下界之间,对该序列二分搜索
    如果没搜到,返回-1,因为在确定范围内未找到元素

    如果目标不在上下界之间,对左边无序序列递归地划分为 有序+无序,转1

代码

class Solution {
public:
    int bisearch(int l, int r, vector<int>& nums, int target)
    {
        if(l <= r)
        {
            int mid = l + (r-l)/2;
            if(nums[mid] == target)
            {
                return mid;
            }
            // 左边有序
            if(l<=mid-1 && nums[l]<=nums[mid-1])
            {
            	// 目标在范围内
                if(nums[l]<=target && target<=nums[mid-1])
                {
                	// 直接二分
                    int res = lower_bound(nums.begin()+l, nums.begin()+mid-1, target) - nums.begin();       
                    if(0<=res && res<nums.size() && nums[res]==target)
                    {
                        return res;
                    }
                    return -1;
                }
                else
                {
                	// 目标不在范围内,递归划分,再搜索
                    return bisearch(mid+1, r, nums, target);
                }
            }
            // 右边有序
            else if(mid+1<=r && nums[mid+1]<=nums[r])
            {
            	// 目标在范围内
                if(nums[mid+1]<=target && target<=nums[r])
                {
                	// 直接二分
                    int res = lower_bound(nums.begin()+mid+1, nums.begin()+r, target) - nums.begin();       
                    if(0<=res && res<nums.size() && nums[res]==target)
                    {
                        return res;
                    }
                    return -1;
                }
                else
                {
                	// 目标不在范围内,递归划分,再搜索
                    return bisearch(l, mid-1, nums, target);
                }
            }
        }
        return -1;
    }
    int search(vector<int>& nums, int target) 
    {
       if(nums.size() < 1)
       {
           return -1;
       }
       return bisearch(0, nums.size()-1, nums, target);
    }
};
发布了171 篇原创文章 · 获赞 7 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_44176696/article/details/104395692