題目:把一個數組最開始的若干個元素搬到數組的末尾,我們稱之爲數組的旋轉。 輸入一個非減排序的數組的一個旋轉,輸出旋轉數組的最小元素。 例如數組{3,4,5,1,2}爲{1,2,3,4,5}的一個旋轉,該數組的最小值爲1。 NOTE:給出的所有元素都大於0,若數組大小爲0,請返回0。
其實一開始做這道題我是拒絕的,因爲題目中直接一個求最小值的操作就可以通過的,所以,一直不想看具體怎麼簡化解答的。
最近得找實習了,不得不拿起了減脂offer(皮.jpg)這本書。又翻到了這一頁。仔細看了看裏面的講述,確實值得簡化。幫助我們去理解二分的操作。類似的還有一個問題就是求數組中的局部最小值,也可以通過這個二分的思想來解答。
題目中已經說得很清楚了,講一個非遞減的數組做了一個定義好的旋轉,所以,將數組分爲了兩部分,第一部分和第二部分都是非遞減的,兩部分交界處類似於一個斷崖。所以,最小值一般都是在懸崖底部,所以,可以通過二分的方法找到這個值。
這裏設置兩個指針,分別是left和right,開始的時候left指向第一部分的開頭,right指向第二部分的結尾。一般情況下,right指向的值是小於或等於left的。這時候我們的任務就是去找那個懸崖,一步一步肯定是有點慢了,這時候採用二分的思想。
確定好中間點之後,讓我們看一下mid指向的值在數組的第一部分還是第二部分,如果在第一部分即array[left]<=array[mid],如果在第二部分即array[mid]>=array[right].這時候,可以通過範圍的縮小來查找這個最小值的存在。
當然存在多個1,一個0的情況,這種情況比較奇葩,因爲整個數組就像平地一樣,那個最小值肯定是坑的存在。這時候,我們需要一點一點的找到這個坑了。就需要在指定的範圍內查找這個最小值。當然,這裏因爲array[left]==array[mid]==array[right],那隻能這樣找了。
/*
*/
public int minNumberInRotateArray(int [] array) {
if (array==null||array.length==0) {
return 0;
}
int left=0;
int right=array.length-1;
while (array[left]>=array[right]) {
if(left-right==1){
return array[right];
break;
}
int mid=(left+right)/2;
if (array[left]==array[mid]&&array[mid]==array[right]) {
return findMin(array,left,mid);
}
if (array[mid]>=array[left]) {
left=mid;
}else if (array[mid]<=array[right]) {
right=mid;
}
}
return array[right];
}
public static int findMin(int[]array,int index1,int index2){
int min=array[index1];
for (int i=index1;i<index2;i++) {
if (min>array[i]) {
min=array[i];
}
}
return min;
}