【剑指offer】面试题8:旋转数组中的最小值

来源:互联网 发布:ios11蜂窝移动数据设置 编辑:程序博客网 时间:2024/05/21 06:57

题目总结:

1.若没有进行旋转,或者说旋转后的效果跟没有旋转是一样的,那么index1指示的值小于index2指示的值,返回index1的值。

2.若是一般性的旋转,那么最小的值旋转后肯定在中间,那么我们就可以从两边向中间夹逼。

3.夹逼的过程中,若 [ index1, middle ] 是有序的,说明这部分子区间没被破坏,旋转所移动的元素都在middle 的后面,那么最小值可定也在后面的部分,令 index1 = middle,继续向后夹逼;同理,若 [ middle ,index2 ] 是有序的,说明这部分子区间也没被最小值破坏,即最小值也没在这里,而应该在前部分,令 index2 = middle,继续向前夹逼,这样两边向中间的收缩,就把最小值确定了。

4.书中说道的 左,中,右相等的时候,无从判断最小值在哪一部分,但可以肯定的是在[ index1, index2] 中,遍历。


int MinInOrder(const vector<int>& nums, int begin, int end){assert(nums.size() > 0);int value_min = nums[begin];while(++begin <= end){if(nums[begin] < value_min)value_min = nums[begin];}return value_min;}int Min(const vector<int>& nums){assert(nums.size() > 0);int index1 = 0;int index2 = nums.size() - 1;int middle = index1;//if index is still in the front partwhile (nums[index1] >= nums[index2]){if(index2 - index1 == 1){middle = index2;break;}middle = (index1 + index2) >> 1;//can't make sure which part the middle belong to.if(nums[middle] == nums[index1] &&nums[middle] == nums[index2])return MinInOrder(nums, index1, index2);//the front part is in orderelse if(nums[middle] >= nums[index1])index1 = middle;//the back part is in order.else if(nums[index2] >= nums[middle])index2 = middle;}return nums[middle];}

除了找最小值,还可以找最大值,思路和这一样,就是找两个区间的断裂处。

这里给定的是一个经过选择的数组,我们试着自己实现下这种旋转。

函数接口如下:

void RotaArray(vector<int>& nums, int roteNums)

nums:给定的要旋转的数组。

roteNums:表示数组的前 roteNums 个数移动到数组的后面。


分析:

我们开始将旋转的两部分视为两个元素,那么目标就是交换着两个元素的位置,看来是要用到交换。

比如 1, 2, 3, 4, 5,将前两个交换到后面,变成 3, 4, 5, 1, 2.

我们首先不管其他交换一下看看。

首尾交换我们得到:5,4,3,2,1.

虽然 1,2 确实到了数组的后面,但是 5,4,3,区间 和 2,1区间是反的。但再看之下,我们发现,在把两个区间各自内部交换下就行了。

5,4,3交换,得到:3, 4, 5

2,1交换,得到:1, 2.

这样就得到:3 ,4 ,5 ,1, 2.

当然先对子区间内部交换再整体交换也是一样的。


void Swap(int& a, int& b){a ^= b;b ^= a;a ^= b;}void Reverse(vector<int>& nums, int begin, int end){if(begin < 0 || end > nums.size())return;while (begin < end){Swap(nums[begin++], nums[end--]);}}void RotaArray(vector<int>& nums, int roteNums){if(nums.size() <= 1 || roteNums == 0 || roteNums >= nums.size())return;Reverse(nums, 0, roteNums - 1);Reverse(nums, roteNums, nums.size() - 1);Reverse(nums, 0, nums.size() - 1);}


1 0
原创粉丝点击