美文网首页
33. 搜索旋转排序数组

33. 搜索旋转排序数组

作者: gykimo | 来源:发表于2020-06-25 16:48 被阅读0次

    https://leetcode-cn.com/problems/search-in-rotated-sorted-array/

    我的方法一:先找到旋转点,然后再确定是在哪一段来二分查找

    步骤:

    1. 判断是否有旋转,即判断第一位是否大于最后一位
    2. 当有旋转时,寻找旋转点
      2.1 begin和end分别表示数组的第一位和最后一位
      2.2 取中间点middle,判断middle是否比middle+1位数要大
      2.2.1 如果大,那么middle就是旋转点
      2.2.2 如果不大,当middle值比第一位小,那么end=middle-1
      2.2.3 如果不大,当middle值比第一位大,那么begin=middle+1
    3. 确定target在哪一段,即求的begin和end

    初始值

    1. begin=0, end=nums.size()-1

    边界条件

    1. begin要<=end
    2. nums的长度是否0或者1

    复杂度

    时间复杂度:O(logn),寻找旋转点和寻找target都采用二分查找
    空间复杂度:O(1),只使用来begin、end、middle几个变量

    代码

    出现一个错误,就是当找到旋转点时一定要break;

    class Solution {
    public:
        int search(vector<int>& nums, int target) {
            if(nums.size()==0){
                return -1;
            }else if(nums.size()==1){
                return nums[0]==target?0:-1;
            }
    
            int begin = 0;
            int end = nums.size()-1;
            int middle = 0;
            //1. 判断是否有旋转,即判断第一位是否大于最后一位
            if(nums[begin] > nums[end]){
                while(begin <= end){
                    //2.2 取中间点middle,判断middle是否比middle+1位数要大
                    middle=(begin+end)>>1;
                    if(nums[middle] > nums[middle+1]){
                        //2.2.1 如果大,那么middle就是旋转点
                        if(nums[middle] == target){
                            return middle;
                        }else if(nums[middle] < target){
                            return -1;
                        }else{
                            if(target >= nums[0] && target<= nums[middle]){
                                begin = 0;
                                end = middle;
                            }else if(target >= nums[middle+1] && target<= nums[nums.size()-1]){
                                begin = middle+1;
                                end = nums.size()-1;
                            }else{
                                return -1;
                            }
                        }
                        break;
                    }else{
                        if(nums[middle] < nums[0]){
                            //2.2.2 如果不大,当middle值比第一位小,那么end=middle-1
                            end = middle-1;
                        }else{
                            //2.2.3 如果不大,当middle值比第一位大,那么begin=middle+1
                            begin = middle+1;
                        }
                    }
                }
            }
    
            //cout<<"begin:"<<begin<<" end:"<<end<<endl;
    
            //3. 确定target在哪一段,即求的begin和end
            while(begin <= end){
                middle = (begin+end)>>1;
                if(nums[middle] == target){
                    return middle;
                }else if(nums[middle] < target){
                    begin = middle+1;
                }else{
                    end = middle-1;
                }
            }
            return -1;
        }
    };
    

    其他人的更好解法

    官方解法

    https://leetcode-cn.com/problems/search-in-rotated-sorted-array/solution/sou-suo-xuan-zhuan-pai-xu-shu-zu-by-leetcode-solut/
    不需要寻找旋转点,直接在原数组上二分查找,思路更加清晰

    步骤

    1. begin和end分别指向要搜索的一段区间
    2. 判断middle
      2.1 如果nums[begin] <= nums[middle],说[begin, middle]是有序的数组
      2.1.1 target==nums[begin], target是begin
      2.1.2 target==nums[middle], target是middle
      2.1.3 target>nums[begin] && nums[middle]> target,那么target肯定在[begin, middle-1]内
      2.1.4 否则[middle+1, end]内
      2.2 如果nums[begin] > nums[middle],说[middle,end]是有序的数组
      2.1.1 target==nums[end], target是end
      2.1.2 target==nums[middle], target是middle
      2.1.3 target>nums[middle] && nums[end]> target,那么target肯定在[middle+1, end]内
      2.1.4 否则[begin, middle-1]内

    代码

    class Solution {
    public:
        int search(vector<int>& nums, int target) {
            if(nums.size()==0){
                return -1;
            }
    
            int begin = 0;
            int end = nums.size()-1;
            int middle = 0;
            
            while(begin <= end){
                middle = (begin+end)>>1;
                //cout << "begin:"<<begin<<" end:"<< end<<" mid:"<<middle<<endl;
                if(nums[begin] <= nums[middle]){
                    if(target == nums[begin]){
                        //2.1.1 target==nums[begin], target是begin
                        return begin;
                    }else if(target == nums[middle]){
                        //2.1.2 target==nums[middle], target是middle
                        return middle;
                    }else if(target > nums[begin] && nums[middle]> target){
                        ////2.1.3 target>nums[begin]  && nums[middle]> target,那么target肯定在[begin, middle-1]内
                        end = middle-1;
                    }else{
                        //2.1.4 否则[middle+1, end]内
                        begin = middle+1;
                    }
                }else{
                    if(target==nums[end]){
                        //2.1.1 target==nums[end], target是end
                        return end;
                    }else if(target==nums[middle]){
                        //2.1.2 target==nums[middle], target是middle
                        return middle;
                    }else if(target>nums[middle] && nums[end]> target){
                        //2.1.3 target>nums[middle]  && nums[end]> target,那么target肯定在[middle+1, end]内
                        begin = middle+1;
                    }else {
                        //2.1.4 否则[begin, middle-1]内
                        end = middle-1;
                    }
                }
            }
    
            return -1;
        }
    };
    

    相关文章

      网友评论

          本文标题:33. 搜索旋转排序数组

          本文链接:https://www.haomeiwen.com/subject/welmxktx.html