您的位置:首页 > Web前端

剑指Offer8 旋转数据的最小数字

2014-08-11 16:39 330 查看

题目:

把一个数组最开始的若干元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2},为{1,2,3,4,5}的一个旋转,该数组的最小值为1.

解题思路1:

最简单的就是暴力办法,从头到尾遍历选出最小元素。其时间复杂度为O(n).

解题思路2:

思路1的方法肯定不是这个题的最优解,那么下面咱们要找这个题目中所给条件,从条件入手一步步分析问题,然后再找出突破口。

首先题目中说这个数组是递增排序的,如题中所给的例子,3,4,5,1,2.是不是可以把它分成两个两个数组,并且会发现这个两个数据都是递增的。如果找两个递增数组的最小值,那么是不是就是找到这个数组的每个最小的元素,然后比较出最小的那个呢?那么我们就会想怎么能把这个数组分成两个数组呢???答案是还是遍历!!所以这个办法也不是特别有效,那我们回过头来想,既然是排序数组,那最先想到应该是二分法查找啊,所以,我们试着用二分法找一下试试。

我们用两个指针,分别指向头和尾。用题目中所给的数据模拟的话,则中间的数是5,那么它比头大,则最小值只能在中间指针的右边,否则的就只能在左边,是不是很简单。但是我们要进行特殊测试的时候会不会想到如果是一个已经排好序的数组,是不是就相当于它本身只移动0个数据呢,那么这么想的话,我们就会想到,如果一开始的头指针就比尾指针小,那么最小元素肯定就头指针了。

但是还有一种类型的数据{1,0,1,1,1},它相当于是{0,1,1,1,1}的变化,如果这样的我们发现此时头、尾、还有中间指针的值是一样大的,那么最小元素在那一部分呢?这样的话我们是无法知道的,只能从头指针到尾指针挨着遍历了

代码:

#include <iostream>

using namespace std;

int minCore(int *data,int startP,int endP)

{

int m = data[startP];

for(int i=startP+1;i<=endP;i++)

if(m>data[i])

m = data[i];

return m;

}

int min(int *data,int length)

{

if(data == NULL || length < 0)

return -1;

int startP = 0,endP = length -1;

int midIndex = startP;

while(data[startP] >= data[endP])

{

if(endP - startP == 1)

return data[endP];

midIndex = (endP + startP)/2;

if(data[startP] == data[midIndex] && data[startP] == data[endP])

return minCore(data,startP,endP);

if(data[startP] <= data[midIndex])

startP = midIndex;

else

endP = midIndex;

}

return data[startP];

}

void test ()

{

int data[] = {2,3,4,5,1};

int length = 5;

int m = min(data,length);

cout<<m<<endl;

}

void test1 ()

{

int data[] = {1,0,1,1,1};

int length = 5;

int m = min(data,length);

cout<<m<<endl;

}

int main()

{

// test();

test1();

cout << "Hello world!" << endl;

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: