剑指Offer_面试题08_旋转数组的最小数字

来源:互联网 发布:乐清人民法院淘宝拍卖 编辑:程序博客网 时间:2024/05/21 05:22


思路: 如序列 3,4,5,1,2   观察到数组旋转后可以分为两个部分,两个排序的子数组,而且前面的元素都不小于后面数组的元素。而且最小值元素刚好是这两个数组的分界线。

在有序数组中可以使用二分查找法实现O(logn)的查找。本题的数组一定程度上也是有序的,因此可以使用二分法的思想来寻找这个最小元素。


如上图所示,a中:array[mid] >= array[p2]说明mid所指还在左边序列中,p1 = mid;

b中:array[mid] >= array[p2]不成立,则说明mid所指已经在右边序列中,p2 = mid;

c中 p2 - p1 == 1 已经到达分界线即上一次的mid位置


特殊情况:有序数组前面0个元素后移,如 1,2,3,4,5  代码应该要考虑这种情况,因此初始化 mid的时候 将mid初始化为0,如果不执行循环则直接返回array[mid].

超特殊情况:10111

这种情况下 array[p1] = array[p2] = array[mid] 无法判断mid所指属于左右哪个序列,这个时候不得不采取顺序查找的方式。 这个情况是本题的第二个关键。第一个是二分思想。

牛客网版本代码:

class Solution {public:    int minNumberInRotateArray(vector<int> rotateArray) {        int p = 0;        int q = rotateArray.size() - 1;        int mid = 0;    //初始化为0,防止首元素即为最小值        while(rotateArray[p] >= rotateArray[q])        {            //分界点            if(q - p == 1)            {                mid = q;                break;            }                        mid = (p + q) / 2;            //元素一样无法二分查找,顺序查找            if(rotateArray[p] == rotateArray[mid] &&               rotateArray[q] == rotateArray[mid])                return minInOrder(rotateArray, p, q);                        if(rotateArray[mid] >= rotateArray[q])                p = mid;            else                q = mid;        }        return rotateArray[mid];    }    //顺序查找最小元素,当序列如1 0 1 1 1时二分查找失效之时    int minInOrder(vector<int> Array, int low, int high)    {        int min = Array[low];        for(int i = low + 1; i <= high; ++i)            if(Array[i] < min)                min = Array[i];        return min;    }};


面对面试提出的新概念,要多跟面试官沟通,多问几个问题吧概念弄清楚。
有序数组本身就是旋转的特例。另外还要考虑数组中有相同数字的特例。如果不能很好地处理这些特例,就很难写出让面试官满意的代码。



阅读全文
0 0
原创粉丝点击