您的位置:首页 > 职场人生

剑指offe面试题8 旋转数组的最小数字 (java实现)

2017-08-10 16:33 561 查看
解题思路:

针对旋转数组的特点,即旋转后,数组的前半部分是有序的,后半部分是有序的。

1.先考虑一般情况:可以参考二分查找的思想,在数组中设置两个指针,一个指向数组的起始位置,一个指向数组的结束位置。随后依据这两个位置求出数组的中间位置mid。如果mid指向元素大于等于start指向元素,则证明mid肯定在数组的前半部分,而旋转数组的最小值在mid的后面,因此可以缩小查找范围,令start = mid;如果mid指向元素小于start指向元素并且小于等于end指向指向元素,则证明mid肯定在数组的后半部分,而最小值在mid之前或者就是mid指向的元素,因此可以缩小查找范围,令end =
mid。直到end - start == 1为止,此时end指向的元素即为旋转数组的最小值。

2.本题还需考虑两种特殊情况:(1)若是这样的旋转数组,即先赚前面的0个元素到后面,即数组还是一开始的排序数组,那么数组中的第一个数字即为最小的元素;(2)当start和end和mid指向元素相同时,此时无法判断mid所指元素属于前半部分还是后半部分,因此只能进行顺序查找。

public class Solution {
/**
* 利用二分查找完成寻找最小的元素
*
* @param array
* @return
*/
public int minNumberInRotateArray(int[] array) {
// 初始化数组的启示索引和结束索引
int firstIndex = 0;
int lastIndex = array.length - 1;
int midIndex = firstIndex;
// 旋转数组中一般情况下第一个元素是大于等于最后一个元素的
// 而如果数组中第一个数字小于最后一个数字,表明该数组本身是排序的,即相当于旋转了前0个元素到后面
while (array[firstIndex] >= array[lastIndex]) {

if (lastIndex - firstIndex == 1) {
midIndex = lastIndex;
break;
}
// 求出中间位置的索引
midIndex = (firstIndex + lastIndex) / 2;

// 如果第一个指针和第二个指针和第三个指针指向的三个数字相等,则只能顺序查找
if (array[firstIndex] == array[lastIndex]
&& array[midIndex] == array[firstIndex]
&& array[midIndex] == array[lastIndex]) {
return minInOrder(array, firstIndex, lastIndex);

}

if (array[midIndex] >= array[firstIndex]) {
// 此时说明中间元素处于左边这个子数组中,而最小的元素位于中间元素的后面
// 将第一个指针指向该中间元素,该指针仍然位于前面这个递增子数组中
firstIndex = midIndex;
} else if (array[midIndex] <= array[lastIndex]) {
// 如果中间元素位于右边的递增子数组,则它所指向元素应该小于等于第二个指针指向的元素
// 此时最小的元素在该中间元素的前面,移动之后的第二个指针仍然在第二个递增子数组中
lastIndex = midIndex;
}

}
// 此时第二个指针指向的元素即为旋转数组中最小的元素
return array[lastIndex];

}

private int minInOrder(int[] array, int firstIndex, int lastIndex) {
int minNum = array[firstIndex];
for (int i = firstIndex + 1; i <= lastIndex; i++) {
if (array[i] < minNum) {
minNum = array[i];
}
}
return minNum;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息