剑指offer:旋转数组的最小数字

Posted licheng-

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指offer:旋转数组的最小数字相关的知识,希望对你有一定的参考价值。

题目描述

一个递增排序的数组的一个旋转(把一个数组最开始的若干元素搬到数组的末尾,称之为数组的旋转),输出旋转数组的最小元素。

解题思路:

旋转之后的数组实际上可以划分成两个有序的子数组:前面子数组的大小都大于后面子数组中的元素 
注意到实际上最小的元素就是两个子数组的分界线。本题目给出的数组一定程度上是排序的,因此我们试着用二分查找法寻找这个最小的元素。 
  
(1)我们用两个指针left,right分别指向数组的第一个元素和最后一个元素。按照题目的旋转的规则,第一个元素应该是大于最后一个元素的(没有重复的元素)。 
但是如果不是旋转,第一个元素肯定小于最后一个元素。 
  
(2)找到数组的中间元素。 
中间元素大于第一个元素,则中间元素位于前面的递增子数组,此时最小元素位于中间元素的后面。我们可以让第一个指针left指向中间元素。 
移动之后,第一个指针仍然位于前面的递增数组中。 
中间元素小于第一个元素,则中间元素位于后面的递增子数组,此时最小元素位于中间元素的前面。我们可以让第二个指针right指向中间元素。 
移动之后,第二个指针仍然位于后面的递增数组中。 
这样可以缩小寻找的范围。 
  
(3)按照以上思路,第一个指针left总是指向前面递增数组的元素,第二个指针right总是指向后面递增的数组元素。 

特殊情况考虑:旋转0个元素、三个指针相等情况(10111, 11101)

//
import java.util.ArrayList;
public class Solution {
public int minNumberInRotateArray(int [] array) {
// 判断特殊情况
if (array==null||array.length==0)
return 0;
int firstIndex = 0;
int lastIndex = array.length - 1;
// 这里初始化mid为0的原因是,如果旋转0个元素那么最小值就是第一个元素
int midIndex = 0;
// 如果旋转0个元素则直接跳出循环
while (array[firstIndex] >= array[lastIndex]){
if (firstIndex+1==lastIndex){
midIndex = lastIndex;
break;
}
// 三指针相等时,只能顺序查找,这种情况非常容易漏,要非常细心
if (firstIndex==lastIndex && firstIndex==midIndex){
return MinInOrder(array, firstIndex, lastIndex);
}
midIndex = (firstIndex + lastIndex) / 2;
if (array[firstIndex] <= array[midIndex]){
firstIndex = midIndex;
}
else{
lastIndex = midIndex;
}
}
return array[midIndex];
}
public int MinInOrder(int [] array, int low, int high){
int ret = array[low];
for (int i=low+1; i<high; i++){
if (array[i] < ret){
ret = array[i];
}
}
return ret;
}
}

以上是关于剑指offer:旋转数组的最小数字的主要内容,如果未能解决你的问题,请参考以下文章

剑指 Offer 11. 旋转数组的最小数字 的详细题解

Java 剑指offer(10) 旋转数组的最小数字

《剑指offer》— JavaScript旋转数组的最小数字

剑指offer旋转数组的最小数字

java刷题-剑指offer 11 旋转数组的最小数字

剑指offer——旋转数组的最小数字