您的位置:首页 > Web前端

重做剑指offer(六)——旋转数组的最小数字

2019-04-16 22:13 344 查看
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/biandi9300/article/details/89309890

重做剑指offer(六)——旋转数组的最小数字


题目描述:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

分析:这一题理解完题意之后应该很快就会有思路,只要找到数组中最小的那个数就好了,这时只需要将整个数组遍历一遍,虽然这样方法简单易理解,但是时间复杂度过大,为O(n),如果用二分法来查找的话,可以大大简化算法的时间复杂度,为O(logn)。于是我们便写出了代码:

import java.util.ArrayList;
public class Solution {
public int minNumberInRotateArray(int [] array) {
int index1 = 0,L = array.length,index2 = L - 1;
int midindex = (index2 - index1)/2;
int min = array[index1];
if(L == 0)
return 0;
if(array[index1] < array[index2])
return array[index1];
while(array[index1] >= array[index2]){
if(index2-index1 == 1)
return Math.min(array[index1],array[index2]);
if(array[midindex] >= array[index1])
index1 = midindex;
else
index2 = midindex;
midindex = (index1 + index2)/2;
}
return array[midindex];
}
}

虽然在牛客网的OJ中可以AC,但是这个算法有一个明显的漏洞,未考虑[1 1 0 1 1]、[1 0 1 1 1]、[1 1 1 0 1]的这些情况,如果遇到数组两端的元素一样大时,运用二分法就不能找到最小的那个元素了,这时就只能用我们最开始的思路,将数组遍历一遍,虽然这样做的时间复杂度为O(n),但不是所以的情况都是需要这样去遍历的,所以时间还是可以大大节约,修改后的代码如下:

import java.util.ArrayList;
public class Solution {
public int minNumberInRotateArray(int [] array) {
int index1 = 0,L = array.length,index2 = L - 1;
int midindex = (index2 - index1)/2;
int min = array[index1];
if(L == 0)
return 0;
if(array[index1] < array[index2])
return array[index1];
while(array[index1] >= array[index2]){
if(array[index1] == array[index2]){		//添加的代码块
for(int i = 1;i < L;i++)
if(min > array[i])
min = array[i];
return min;
}
if(index2-index1 == 1)
return Math.min(array[index1],array[index2]);
if(array[midindex] >= array[index1])
index1 = midindex;
else
index2 = midindex;
midindex = (index1 + index2)/2;
}
return array[midindex];
}
}

知识点总结:从这题中我们用到了二分法去查找元素,但二分法一般用于已经有序,或是有一定规律的数组,并不是适用于所有的情况,所有,我们在考虑问题时要特别注意考虑到所有的情况,不能让程序出现漏洞。

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