劍指offer面試題11:旋轉陣列的最小數字(Java版已在牛客網AC)
題目
把一個陣列最開始的若干個元素搬到陣列的末尾,我們稱之為陣列的旋轉。 輸入一個非減排序的陣列的一個旋轉,輸出旋轉陣列的最小元素。 例如陣列{3,4,5,1,2}為{1,2,3,4,5}的一個旋轉,該陣列的最小值為1。 NOTE:給出的所有元素都大於0,若陣列大小為0,請返回0。
思路
看到這道題,最常規的解法是順序查詢,從頭到尾遍歷一邊陣列就可以得到最小元素了,這種思路的時間複雜度顯然就是O(n)。但是我們仔細閱讀題後,可以發現旋轉後的陣列實際可以劃分成兩個排序的子陣列,而且前面的子陣列的元素都大於或者等於後面子陣列的元素,同時我們可以發現最小的元素剛好是這兩個子陣列的分界線。在有序的陣列中我們可以使用二分查詢法來查詢最小的元素,該方法的時間複雜度為O(log n),具體思路如下:
- 用兩個指標分別指向陣列的第一個元素和最後一個元素,按照題目的規則,第一個元素應該是大於或者等於最後一個元素的。
- 找到第一個指標和第二個指標中間的元素
- 如果該中間元素位於前面的遞增陣列,則它應該大於或者等於第一個指標指向的元素。此時陣列中最小的元素應該位於該中間元素的後面,因此我們把第一個指標指向該中間元素,這樣可以縮小查詢範圍。移動之後第一個指標任然位於前面的遞增子陣列。
- 如果該中間元素小於或者等於第二個指標指向的元素,說明中間元素位後面的遞增子陣列,此時陣列中最小的元素應該位於該中間元素的前面,因此我們將第二個指標指向該中間元素,可以縮小查詢範圍。移動之後第二個指標任然位於後面的遞增子陣列。
- 用更新後的兩個指標重複做上面的操作,直到最後,第一個指標總會指向前面遞增子陣列中的最後一個元素,第二個指標總會指向後面遞增子陣列中的第一個元素,此時,第一個指標指向的元素和第二個指標指向的元素相鄰,而第二個指標指向的元素剛好是該陣列中最小的元素。
以陣列{3,4,5,1,2}為例
- 首先我們將第一個指標指向第0個元素 3,將第二個指標指向第4個元素 2
- 接著找到他兩的中間元素 5
- 因為5大於第一個指標指向的元素,因此最小元素應該在5的後面,所以將第一個指標指向該中間元素 5
- 接著繼續找第一個指標和第二個指標的中間元素 1
- 因為1 小於第二個指標指向的元素,所以該陣列中最小的元素應該在該該中間元素1前面,所以將第二個指標指向該中間元素 1
- 此時第一個指標指向的元素剛好和第二個指標指向的元素相鄰
- 因此判斷第二個指標指向的元素 1 為該陣列中最小的元素
注意
上述例子屬於常規情況,但總會有特殊情況出現,例如
- 如果將排序陣列的前面的0個元素搬到後面,即排序陣列本身任然是一個反轉,例如陣列{1,2,3,4,5},第一個元素就是最小值
- 如果旋轉陣列為{1,0,1,1,1},是{0,1,1,1,1}的旋轉,這種情況下,第一個指標指向的元素等於第二個指標指向的元素等於中間元素,如果繼續用上述解決方法則會出現問題,因為此時我們無法判斷中間元素是屬於前面遞增子陣列還是屬於後面遞增子陣列。這種情況下就需要對採用順序查詢啦。
程式碼實現
publicc int minNumberInRotateArray(int [] array) {
int index1=0;//指向陣列第0個元素
int index2=array.length-1;//指向陣列最後一個元素
int indexMid=index1;//用來處理第一種特殊情況
while(array[index1]>=array[index2])
{
if(index2-index1==1)//查詢結束條件
{
indexMid=index2;
break;
}
indexMid=(index1+index2)/2;//找到中間元素的下標
//用來處理第二種特殊情況
if(array[index1]==array[index2]&&array[index2]==array[indexMid])
{
return minInOrder(array,index1,index2);
}
//當中間元素大於等於第一個指標指向的元素
if(array[indexMid]>=array[index1])
{
index1=indexMid;
}
//當中間元素小於等於第二個指標指向的元素
else if(array[indexMid]<=array[index2])
{
index2=indexMid;
}
}
return indexMid;
}
//第二種特殊情況的處理,就是採用順序查詢,通過遍歷陣列來查詢最小值
public int minInOrder(int[] array,int index1,int index2)
{
int result=array[index1];
for(int i=index1;i<=index2;i++)
{
if(result>array[i])
{
result=array[i];
}
}
return result;
}
相關文章
- 劍指offer面試題12:矩陣中的路徑(Java版已在牛客網AC)面試題矩陣Java
- 劍指 Offer 11. 旋轉陣列的最小數字陣列
- 【劍指 Offer】11. 旋轉陣列的最小數字陣列
- 劍指offer:旋轉陣列的最小數字陣列
- 劍指offer 旋轉陣列的最小數字陣列
- 【劍指offer】7.旋轉陣列的最小數字陣列
- 0二分查詢簡單 牛客NC.71旋轉陣列的最小數字 leetcode劍指 Offer 11. 旋轉陣列的最小數字陣列LeetCode
- (python版)《劍指Offer》JZ06:旋轉陣列的最小數字Python陣列
- 【劍指offer】旋轉陣列的最小值陣列
- 劍指offer-轉陣列的最小數字-php陣列PHP
- 【劍指offer】把陣列排成最小的數陣列
- 面試:Java 實現查詢旋轉陣列的最小數字面試Java陣列
- 二維陣列中的查詢——牛客劍指offer陣列
- 劍指Offer-34-把陣列排成最小的數陣列
- 劍指offer——把陣列排成最小的數C++陣列C++
- 力扣 - 劍指 Offer 45. 把陣列排成最小的數力扣陣列
- 劍指Offer--陣列中重複的數字陣列
- 《劍指offer》:[51]陣列中的重複數字陣列
- 劍指OFFER-數字在升序陣列中出現的次數(Java)陣列Java
- 劍指Offer-把陣列中的數排成一個最小的數陣列
- 劍指offer面試題11 數值的整數次方面試題
- 【劍指offer】數字在排序陣列中出現的次數排序陣列
- 我請大家來刷題:旋轉陣列的最小數字陣列
- [劍指offer題解][Java]陣列中出現次數超過一半的數字Java陣列
- 劍指offer刷題之路--1.陣列中重複的數字陣列
- 劍指offer(java實現)第5題“用兩個棧實現佇列”-牛客網Java佇列
- 《劍指offer》:[38]數字在排序陣列中出現的次數排序陣列
- 劍指offer(java實現)第4題“重建二叉樹”-牛客網Java二叉樹
- 劍指Offer-39-數字在排序陣列中出現的次數排序陣列
- 劍指 Offer 56 - I. 陣列中數字出現的次數陣列
- 《劍指Offer》- 連續子陣列的最大和或最小和陣列
- 劍指offer之列印超過陣列一半的數字陣列
- 劍指offer 陣列中只出現一次的數字陣列
- 劍指 offer(1) -- 陣列篇陣列
- Leetcode 劍指 Offer 03. 陣列中重複的數字LeetCode陣列
- 《劍指offer》:[40]陣列中只出現一次的數字陣列
- 【劍指offer】陣列中只出現一次的數字(1)陣列
- 【劍指offer】陣列中只出現一次的數字(2)陣列