LeetCode-33:搜索旋转排序数组

一、题目描述

在这里插入图片描述

二、解题思路

要求在 O ( l o g n ) O(logn) 的时间复杂度内确定序列里是否存在这个数字,只能采用二分法
从旋转的方式可以看出,是把较大的那一半放到前面来了,从而导致原序列区间有序,我们可以确定这个区间的分割点,然后在两个区间内二分查找。
这种方法一定可以把原序列分成有序的一半和不一定有序的另一半。
但是这样有个问题,二分查找需要保证原序列递增有序,那我们怎么判断传入的区间序列是否为区间有序?答案是比较区间首尾元素大小关系,如果首大尾小,就不是有序序列,这个关系也可以用在算法的开头,以排除原序列本身就有序的情况。
特殊情况的排除:如果序列为空,直接返回-1
由此,我们得出:

  • 首先根据首尾大小关系判断初始序列是否有序,若有序,直接二分查找初始序列
  • 选定序列中点为分割点,将序列分割为左右两部分
  • 如果左序列有序,右序列无序,那么现在左序列里二分查找,找到了直接返回,否则对把序列的起点更新为右序列的起点,从而将序列长度缩短一半,在右序列里重复上述过程
  • 如果左序列无序,右序列有序,那么现在右序列里二分查找,找到了直接返回,否则对把序列的起点更新为左序列的终点,从而将序列长度缩短一半,在左序列里重复上述过程
  • 如果刚好分割点把序列分割成有序的两段,在有序的两段里分别进行二分查找,找不到返回-1,否则返回找到的位置

三、解题代码

非递归

class Solution {
public:
    int search(vector<int>& nums, int target) {
        if(!nums.size())    return -1;
        int left = 0, right = nums.size() - 1;
        while(left <= right){
            int loc;
            if(nums[left] <= nums[right])
                return SearchInA_SortedArray(nums, left, right, target, loc) ? loc : -1;
            
            int pivotpos = (left + right) / 2;            
            if(nums[pivotpos + 1] >= nums[right] && nums[left] <= nums[pivotpos])
                if(SearchInA_SortedArray(nums, left, pivotpos, target, loc))
                    return loc;
                else
                    left = pivotpos + 1;
            else if(nums[pivotpos + 1] <= nums[right] && nums[left] >= nums[pivotpos])
                if(SearchInA_SortedArray(nums, pivotpos + 1, right, target, loc))
                    return loc;
                else
                    right = pivotpos;
            else if(nums[pivotpos + 1] <= nums[right] && nums[left] <= nums[pivotpos]){
                int tmpl, tmpr;
                if(SearchInA_SortedArray(nums, left, pivotpos, target, tmpl) || SearchInA_SortedArray(nums, pivotpos + 1, right, target, tmpr))
                    return max(tmpl, tmpr);
                return -1;
            }
        }
        return -1;
    }
private:
    bool SearchInA_SortedArray(vector<int>& nums, int left, int right, int target, int& loc){
        if(left <= right){
            loc = -1;
            while(left <= right){
                int mid = (left + right) / 2;
                if(nums[mid] == target){
                    loc = mid;
                    return true;
                }
                else if(nums[mid] < target)    left = mid + 1;
                else    right = mid - 1;
            }
        }
        return false;
    }
};

递归

class Solution {
private:
    int Search(vector<int>& nums, int l, int h, int target) {
        if(l > h)
            return -1;
        int m = (l + h) >> 1;
        if(nums[m] == target)   return m;
        if(nums[m] < nums[h]){
            if(nums[m] < target && target <= nums[h])
                return Search(nums, m + 1, h, target);
            else
                return Search(nums, l, m - 1, target); 
        }
        else{
            if(nums[l] <= target && target < nums[m])
                return Search(nums, l, m - 1, target);
            else
                return Search(nums, m + 1, h, target);
        }
    }
public:
    int search(vector<int>& nums, int target) {
        return Search(nums, 0, nums.size() - 1, target);
    }
};

三、运行结果

非递归
在这里插入图片描述
递归
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_44587168/article/details/105802658