LeetCode | Search in Rotated Sorted Array(在旋转数组中查找)

来源:互联网 发布:松江少儿编程 编辑:程序博客网 时间:2024/06/04 18:26


Suppose a sorted array 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.


题目解析:

方案一:暴力方法,一个一个比较,最后找到坐标位置。O(n)时间复杂度,最不高效的算法。

方案二:利用二分查找,但是这个题目是分块有序的,于是想到了一个方案,找到分割点,然后再根据值所在的范围,选其中一个区域进行二分搜索。但是实现中遇到了不小的麻烦,本身二分查找的代码就很巧,什么时候要加等号,什么时候不加等号,当涉及到在二分查找上加条件的时候,就更容易出错,网上有个代码方案:找到最小值的位置:

利用二分查找找到转折点,也就是最小值的位置,当a[left]<=a[mid]时,那么在left...mid之间是有序的,a[left]为最小值,或者在mid+1...right之间取最小值,最后取两者最小。

对于a[left]>a[mid]也有类似的思想。随后再利用二分查找来查询位置。

class Solution {public:    int findPos(int a[], int left, int right)    {        if (left > right)            return -1;                    int mid = left + (right - left) / 2;                if (a[left] <= a[mid])        {            int pos = findPos(a, mid + 1, right);                        if (pos == -1)                return left;            else                return a[left] < a[pos] ? left : pos;         }        else        {            int pos = findPos(a, left, mid - 1);                        if (pos == -1)                return mid;            else                return a[pos] < a[mid] ? pos : mid;        }    }        int bsearch(int a[], int left, int right, int key)    {        if (left > right)            return -1;                    int mid = left + (right - left) / 2;                if (a[mid] == key)            return mid;        else if (a[mid] < key)            return bsearch(a, mid + 1, right, key);        else            return bsearch(a, left, mid - 1, key);    }        int search(int A[], int n, int target) {        // Start typing your C/C++ solution below        // DO NOT write int main() function        int pos = findPos(A, 0, n - 1);                int index = bsearch(A, 0, pos - 1, target);        if (index != -1)            return index;                    return bsearch(A, pos, n - 1, target);    }};

整个的思想是很正常的,但是实现起来也有不小的难度,各种细节需要注意。


方案三:

分析方法,代码中分割情况进行了变换,当没查询到值时,不再是A[mid] 与 target之间的比较了,而是换成了A[mid] > A[right]的关系比较,在这种情况下,还合并了多种可能。通过深入分析情况得出的结果代码。

思路很简单:

当a[left] <= a[mid]的时候,这段区域是有序的,判断target是否在这个区域中,是的话,就更改right。

当a[left]>a[mid]的时候,mid...right区域是有序的,判断target和a[mid] a[right]的关系就能确定是否在这个区域中

class Solution {public:    int search(int A[], int n, int target) {        if(NULL == A || 0 == n)    return -1;int left = 0, right = n-1, mid = 0;while(left <= right){mid = left+(right-left)/2;if(A[mid] == target)return mid;else if(A[left] <= A[mid])//这里比较的时候,不再是以中间值与target之间的比较,而是区域比较。{if(A[left] <= target && target < A[mid])    //将各种情况合并right = mid - 1;elseleft = mid + 1;}else//right{if(A[mid] < target && target <= A[right])left = mid + 1;elseright = mid - 1;}}return -1;    }};



方案四:

递归的思想,要准确的掌握好!我们碰到的二分查找,都是利用非递归来求解的,如果我们碰到在二分查找基础上增强条件时,用非递归会出现很多意外情况。但是,利用递归的话,思路会很简单!

利用mid判断与a[lo]的关系后,如果是有序的,那么根据target与该区间的范围,就可以知道应在哪段区域之间进行递归了!思路很简单,代码也很容易写出。

class Solution {public:    int search(int A[], int n, int target) {        if(n<=0)            return -1;        return BinarySearch(A,0,n-1,target);    }    int BinarySearch(int A[],int lo,int hi,int target){        if(lo>hi)            return -1;        int mid = (lo + hi)/2;        if(A[mid] == target)            return mid;        if(A[lo]<=A[mid]){  //这里要加等号,避免mid和lo相等时的情况。            if(target>=A[lo] && target <= A[mid])   //找寻的结果在lo...mid的有序区间,进行递归求解                return BinarySearch(A,lo,mid-1,target);            else                                    //找寻的结果在另一半区间,进行递归                return BinarySearch(A,mid+1,hi,target);        }else{            if(target>A[mid] && target <= A[hi])                return BinarySearch(A,mid+1,hi,target);            else                return BinarySearch(A,lo,mid-1,target);        }    }};



0 0
原创粉丝点击