zoukankan      html  css  js  c++  java
  • 【LeetCode & 剑指offer刷题】查找与排序题6:33. Search in Rotated Sorted Array(系列)

    【LeetCode & 剑指offer 刷题笔记】目录(持续更新中...)

    33. Search in Rotated Sorted Array

    Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
    (i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2]).
    You are given a target value to search. If found in the array return its index, otherwise return -1.
    You may assume no duplicate exists in the array.
    Your algorithm's runtime complexity must be in the order of O(log n).
    Example 1:
    Input: nums = [4,5,6,7,0,1,2], target = 0
    Output: 4
    Example 2:
    Input: nums = [4,5,6,7,0,1,2], target = 3
    Output: -1
     
     
    /* 掌握
    问题:在旋转数组中查找(不存在重复数字)
    方法:二分查找,先找有序范围,再判断有序范围内有没有,更新leftright指针,不断缩小范围
     
    O(logn)
    */
    class Solution
    {
    public:
        int search(vector<int>& a, int target)
        {
            if (a.empty()) return -1;
           
            int left = 0, right = a.size() - 1;
            while (left <= right)
            {
                int mid = (left + right) / 2;
               
                if(a[mid] == target)
                    return mid;
                else if (a[mid] < a[right]) //若中间数小于最右边的数,则右半段(mid~right)是有序的
                {
                    if (target > a[mid] && target <= a[right]) //在有序的半段里用首尾两个数来判断目标值是否在这一区域内
                        left = mid + 1;//说明在mid~right内,更新left位置
                    else
                        right = mid - 1;
                }
                else                        //若中间数大于最右边的数,则左半段(left~mid)是有序的
                {
                    if (target >= a[left] && target < a[mid])//由于判断下来不可能有 target = a[mid],故这里没有取等号
                        right = mid - 1;//说明在left~mid内,更新right位置
                    else
                        left = mid + 1;
                }
            }
            return -1;
        }
    };
     
    //此方法技巧性较高,了解即可
    //方法:二分查找(因为有O(logn)的限制)
    class Solution
    {
    public:
        int search(vector<int>& a, int target)
        {
            if(a.empty()) return -1; //特殊情况:空数组
           
            //使用二分查找找到最小值的索引(旋转的地方)
            //旋转之后左半边数组比右半边数组大,通过二分查找,找到分界点(最小值)即可,最小值在左半数组最末尾,右半数组起始位置
            int n = a.size();
            int left=0,right = n-1;
            int indexmin = 0; //初始化最小值的位置
            while(a[left] > a[right]) //特殊情况:输入有序数组,可以看成rotate 0,则直接退出循环,indexmin用初始值0
            {
                int mid = (left+right)/2;
                if(a[mid]>a[right]) left = mid;//a[mid]>a[right]说明mid在左半边数组,将left指针移至mid
                else right = mid; //a[mid]<a[right]说明mid在右半边数组,将right指针移至mid
                if(right-left == 1)
                {
                    indexmin = right;break;//跳出循环
                }
            }//循环结束后left指向左半数组末尾,right指向右半数组开头
            //找序列中的极小值(联系find peak element这题)
            left = 0;right = n-1;
            //使用常规的二分查找(对于增序序列而言),并考虑旋转
            while(left <= right)
            {
                int mid = (left+right)/2;
                int realmid = (mid+indexmin)%n; //indexmin为数组中最小数的位置(本来为0位置,现在变为rot位置),相当于附加偏移以找到真正的mid位置
                if(a[realmid] < target) left = mid+1;
                else if(a[realmid] > target) right = mid-1;
                else return realmid;
            }
            return -1;//未找到    
        }
    };
     
     
    81. Search in Rotated Sorted Array II
    Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
    (i.e., [0,0,1,2,2,5,6] might become [2,5,6,0,0,1,2]).
    You are given a target value to search. If found in the array return true, otherwise return false.
    Example 1:
    Input: nums = [2,5,6,0,0,1,2], target = 0
    Output: true
    Example 2:
    Input: nums = [2,5,6,0,0,1,2], target = 3
    Output: false
    Follow up:
    • This is a follow up problem to Search in Rotated Sorted Array, where nums may contain duplicates.
    • Would this affect the run-time complexity? How and why?

     
    /*
    问题:在旋转数组中查找2(可以存在重复数字)
    方法:二分查找,先找有序范围,再判断有序范围内有没有,更新leftright指针,不断缩小范围
    如果a[mid]a[right]相等,则让right--直到不相等,其余部分与问题Search in Rotated Sorted Array I相同
    O(logn)
    */
    class Solution
    {
    public:
        bool search(vector<int>& a, int target)
        {
            if (a.empty()) return false;
           
            int left = 0, right = a.size() - 1;
            while (left <= right)
            {
                int mid = (left + right) / 2;
               
                if(a[mid] == target)
                    return true;
                else if (a[mid] < a[right]) //若中间数小于最右边的数,则右半段(mid~right)是有序的
                {
                    if (target > a[mid] && target <= a[right]) //在有序的半段里用首尾两个数来判断目标值是否在这一区域内
                        left = mid + 1;//说明在mid~right内,更新left位置
                    else
                        right = mid - 1;
                }
                else if (a[mid] > a[right]) //若中间数大于最右边的数,则左半段(left~mid)是有序的
                {
                    if (target >= a[left] && target < a[mid])//由于判断下来不可能有 target = a[mid],故这里没有取等号
                        right = mid - 1;//说明在left~mid内,更新right位置
                    else                   
                        left = mid + 1;
                }
                else             //若中间数等于最右边数,移动right指针
                    right--;
            }
            return false;
        }
    };
     
     
     
     
  • 相关阅读:
    mysql安装问题
    决策树算法实现
    安装scipy失败提示lapack not found
    算法复杂度分析中的符号(Θ、Ο、ο、Ω、ω)简介
    VMware 注册码
    chrome浏览器频繁卡死
    dell装系统
    关于scipy包的安装
    pip安装python包时报字符编码错
    linux中mv命令使用详解
  • 原文地址:https://www.cnblogs.com/wikiwen/p/10225932.html
Copyright © 2011-2022 走看看