leetcode——Search in Rotated Sorted Array

来源:互联网 发布:python 变量生存期 编辑:程序博客网 时间:2024/06/06 17:40

题目:

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.

指导思想:二分查找

    二分查找维护两个指针first和last,在迭代过程中必须保证first指向待查找元素的左边(包括待查找元素),last指向待查找元素的右边(不包括待查找元素)且first和last之间的距离变短,这一不变条件一定要至死捍卫!

    本题遵循上述的原则,也可以采用二分查找的策略在旋转有序数组中进行目标查找。但是有一个注意点就是需要判断mid(first和last的中间位置)在待查找元素target的左边还是右边,如果mid在target的左边,那么first = mid + 1;如果mid在target的右边,那么last = mid(备注)。代码中首先判断mid和target是不是在同一段中,然后再根据nums[mid]和target的大小关系确定mid和target的先后顺序。

备注:

1、为什么不是“first = mid”?   答:当last  = first + 1的时候mid会永远等于first,first和last之间的距离没有变短——违背原则

2、为什么不是“last = mid - 1”?  因为nums[mid-1]有可能等于target,此时nums[last] == target——违背原则

    代码首先实现了普通二分查找函数,一来练练手,二来当first,last在同一段中的时候调用之可以提高整个程序的效率。

class Solution {public:    //针对一般的排序数组的二分查找法,区间[first,last)定义了查找范围    int binarySearch(vector<int>& nums, int first, int last, int target)    {        //first指向未放弃位置,last指向已经放弃的位置,保持这个原则        while (first < last)        {            if (nums[first] == target)            {                return first;            }            int mid = first + (last - first) / 2;//防止溢出            if (nums[mid] == target)            {                return mid;            }            //mid已经指向放弃的位置了            if (nums[mid] < target)            {                first = mid + 1;//不能first = mid,一来违背了first指向未放弃位置的原则,二来mid可能等于first,这样会陷入死循环            }            else            {                last = mid;//last指向放弃的位置            }        }        //while退出显然first指向了放弃的位置,也就是找不到了        return -1;    }    //如果first和last处在同一个排序数组中,那么就使用binarySearch()函数搜索    int search(vector<int>& nums, int target) {        if (nums.empty())        {            return -1;        }        if (nums.size() == 1)        {            return nums[0] == target ? 0 : -1;        }        //先判断target在前段还是后段        int firstValue = nums[0];//用来判断一个元素属于第一段还是第二段        bool t_isInFirst = false;        if (target > firstValue)        {            t_isInFirst = true;//在前段        }        int first = 0, last = nums.size();//last不指向有效位置        while (first < last)        {            if (nums[first] == target)            {                return first;            }            int mid = first + (last - first) / 2;//防止溢出            if (nums[mid] == target)            {                return mid;            }            bool m_isInFirst = false;            if (nums[mid] >= firstValue)            {                m_isInFirst = true;            }            /*我们的目的就是确定mid和target的前后顺序*/            if (t_isInFirst == m_isInFirst)//target和mid在同一段            {                if (nums[mid] < target)                {                    first = mid + 1;                    if (!t_isInFirst)//旋转排序数组可以退化为普通排序数组                    {                        //减少比较次数,提高效率                        return binarySearch(nums, first, last, target);                    }                }                else                {                    last = mid;                    if (t_isInFirst)//旋转排序数组可以退化为普通排序数组                    {                        //减少比较次数,提高效率                        return binarySearch(nums, first, last, target);                    }                }            }            else if(t_isInFirst)//target在前一段,mid在后一段            {                last = mid;            }            else//target在后一段,mid在前一段            {                first = mid + 1;            }        }        return -1;    }};


0 0
原创粉丝点击