劍指offer----旋轉陣列的最小數字----java實現
把一個數組最開始的若干個元素搬到陣列的末尾,我們稱之為陣列的旋轉。輸入一個遞增排序的陣列的一個旋轉,輸出旋轉陣列的最小元素。例如陣列{3,4,5,1,2}為{1,2,3,4,5}的一個旋轉,該陣列的最小值為1。NOTE:給出的所有元素都大於0,若陣列大小為0,請返回0。
如果直接遍歷陣列,時間複雜度為O(n),可以利用旋轉陣列的特性來解決此題;
思路:
(1)如果發生旋轉,前面的數至少去了一個放在陣列的後面;
1)旋轉後,陣列分為兩個排序陣列,而且前一個數組中的數均大於等於後一個數組中的數,因為要查詢陣列中的最小數,也就是第二個陣列中的第一個數,可以採用二分查詢的思想;
2)設定兩個指標p1,p2
如果中間位置mid的數大於p1指向的數,則mid在第一個陣列中,讓p1指向mid所指向的數,p1指向的依然是陣列1的數;
如果中間位置mid的數小於p2所指向的位置,則mid在第二個陣列中,p2指向mid指向的數,p2指向的依然是陣列2的數;
Mid不是指向陣列1的數,就是指向陣列2的數,指向陣列1的數,就讓p1移動到mid的位置,指向陣列2就讓p2陣列移動到mid的位置;直到p2移動到陣列1的結束的位置,p1移動到陣列2的開始的位置,此時p2與p1挨著,而且
(2)如果中間位置的數既等於p1位置數,又等於p2位置的數,這時候,不能確定移哪個指標,就必須採用順序查詢的方法來尋找最小數;
總結:此題就是利用兩個指標,一個往後移,一個往前移,具體怎麼移,通過mid的大小控制;直到兩個指標的位置挨著,就可以找到最小數了!
還需要考慮:
如果陣列取0個放在了陣列的後面,也就是排序陣列沒有變,這時p1指向的數小於p2指向的數;直接是陣列的首元素是最小的數;
import java.util.ArrayList; public class Solution { public int minNumberInRotateArray(int [] array) { if(array == null || array.length == 0) { return 0; } int p1 = 0;//從前往後走 int p2 = array.length-1;//從後往前走 int min = array[p1];//如果沒發生旋轉,直接將array[0]的值返回, int mid = 0; //當陣列發生旋轉了, while(array[p1] >= array[p2]) { //當兩個指標走到挨著的位置時,p2就是最小數了 if(p2 - p1 == 1) { min = array[p2]; break; } mid = (p1 + p2)/2; //如果中間位置的數既等於p1位置的數又等於P2位置的數 if(array[p1] == array[mid]&&array[p2]==array[mid]) { min = minInorder(array,p1,p2); } if(array[p1] <= array[mid])//若中間位置的數位於陣列1,讓p1走到mid的位置 { p1 = mid; } else if(array[p2] >= array[mid])//若中間位置的數位於陣列2,讓p2走到mid的位置 { p2 = mid; } } return min; } private int minInorder(int[]array,int p1,int p2) { int min = array[p1]; for (int i = p1 + 1; i <= p2; i++) { if(min > array[i]) { min = array[i]; } } return min; } }