剑指Offer(五)旋转数组的最小数字 矩阵中的路径
题目:
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
思路:
遍历等于白给 O(n)
比 O(n) 更小的是 logn
可以想到二分
由于整个数组是有序的,那么对于 旋转后的数组也是部分有序的,可以分为较大数组(前面的一部分数)
较小数组(后面的数) ,最小数组刚好是这两个数组的分界线. 对于排序好的数组,我们可以使用二分来找到想要的数.
例子:
定义三个变量
第一个指向 大数组中的数 0
第二个指向 小数组中的数 length-1
第三个指向 数组中间的数
普通例子 3 4 5 1 2
第一个指针指向 3 第二个指向2
mid 是 5
此时 3 <5
将 mid 给 index1
index1 指向 5
------新的循环
此时index 1 指向的数还是大于 index 2 的数 5 >2
mid 指向了 1 且 1 < index2 将index2 指向 1
------新的循环
此时 idex2 指向的数与 index1 指向的数 的下标 相差为1
则此时 index2 指向的数就是所要查找的数
代码:
public int minNumberInRotateArray(int[] array)
{
if (array.length == 1)
{
return 0;
}
int index1 = 0;
//如果只旋转了 0 个数字 且 则第一个数字为整个数组中最小的
int index2 = array.length - 1;
int mid = 0;
while (array[index1] >= array[index2])
{
if (index2 - index1 == 1)
//当 第二个指针和第一个指针相差 1 时, 指针2 指向的数就是要找的数
// 此时 第一个指针指向了 较大数组中的最后一个数
{
mid = index2;
break;
}
/**
* 考虑特殊情况
*
* 0 1 1 1 1 的旋转 1 0 1 1 1
*
* 按照 未修改的办法解决肯定是错的
* 此时只能按顺序去寻找 数组中最小的数
*当 第一个指针 第二个指针 中间的数 三个位置上的数一样时 进行顺序遍历
*/
if (array[index1]==array[index2]&&array[index1]==array[mid])
{
mid = find(array);
return mid;
}
mid = (index1 + index2) >> 1;
if (array[mid] >= array[index1])
// 整个数组中间的数 大于 第一个数 那中间的数还在前面的数组中
// 修改指针 将第一个指针 指向 当前中间的数
{
index1 = mid;
}
else if (array[mid] <= array[index2])
//整个数组中间的数 小于 最后一个数 那中间的数还在后面较小的数组中
//修改 指针 将第二个指针指向 当前中间的数
{
index2 = mid;
}
} return array[mid];
}
参考:https://blog.csdn.net/elpsycongr00/article/details/85222800