題目:把乙個陣列最開始的若干個元素搬到陣列的末尾,我們稱之為陣列的旋轉。輸入乙個遞增排序的陣列的乙個旋轉,輸出旋轉陣列的最小元素。例如陣列為的乙個旋轉,該陣列的最小值為1。這道題最直觀的解法並不難,從頭到尾遍歷陣列一次,我們就能找出最小的元素。這種思路的時間複雜度顯然是o(n)。但是這個思路沒有利用輸入的旋轉陣列的特性,肯定達不到面試官的要求。
我們注意到旋轉之後的陣列實際上可以劃分為兩個排序的子陣列,而且前面的子陣列的元素都大於或者等於後面子陣列的元素。我們還注意到最小的元素剛好是這兩個子陣列的分界線。在排序的陣列中我們可以用二分查詢法實現o(logn)的查詢。
step1.和二分查詢法一樣,我們用兩個指標分別指向陣列的第乙個元素和最後乙個元素。
step2.接著我們可以找到陣列中間的元素:
如果該中間元素位於前面的遞增子陣列,那麼它應該大於或者等於第乙個指標指向的元素。此時陣列中最小的元素應該位於該中間元素的後面。我們可以把第乙個指標指向該中間元素,這樣可以縮小尋找的範圍。移動之後的第乙個指標仍然位於前面的遞增子陣列之中。如果中間元素位於後面的遞增子陣列,那麼它應該小於或者等於第二個指標指向的元素。此時該陣列中最小的元素應該位於該中間元素的前面。
step3.接下來我們再用更新之後的兩個指標,重複做新一輪的查詢。
按照上述的思路,第乙個指標總是指向前面遞增陣列的元素,而第二個指標總是指向後面遞增陣列的元素。最終第乙個指標將指向前面子陣列的最後乙個元素,而第二個指標會指向後面子陣列的第乙個元素。也就是它們最終會指向兩個相鄰的元素,而第二個指標指向的剛好是最小的元素。這就是迴圈結束的條件。以前面的陣列為例,下圖展示了在該陣列中查詢最小值的過程:
//把indexmid初始化為index1的原因:
//一旦發現陣列中第乙個數字小於最後乙個數字,表明該陣列是排序的
//就可以直接返回第乙個數字了
int indexmid =index1;
while (numbers[index1] >=numbers[index2])
indexmid = (index1 + index2) / 2
;
//特殊情況:如果下標為index1、index2和indexmid指向的三個數字相等,則只能順序查詢
if (numbers[index1] == numbers[indexmid] && numbers[indexmid] ==numbers[index2])
//縮小查詢範圍
if (numbers[indexmid] >=numbers[index1])
else
if (numbers[indexmid] <=numbers[index2])
}return
numbers[indexmid];
}public
static
int getmininorder(int numbers, int index1, int
index2)
}return
result;
}這裡需要注意的是:
(1)把indexmid初始化為index1的原因:一旦發現陣列中第乙個數字小於最後乙個數字,表明該陣列是排序的,就可以直接返回第乙個數字了。
(2)特殊情況的分析:如果下標為index1、index2和indexmid指向的三個數字相等,則只能順序查詢,因此這裡定義了乙個getmininorder()方法。
(1)典型輸入,單調公升序的陣列的乙個旋轉
//(2)有重複數字,並且重複的數字剛好的最小的數字典型輸入,單調公升序的陣列的乙個旋轉
[testmethod]
public
void
getminnumtest1()
;assert.areequal(program.getmin(array),1);
}
//(3)有重複數字,但重複的數字不是第乙個數字和最後乙個數字有重複數字,並且重複的數字剛好的最小的數字
[testmethod]
public
void
getminnumtest2()
;assert.areequal(program.getmin(array), 1);
}
//(4)有重複的數字,並且重複的數字剛好是第乙個數字和最後乙個數字有重複數字,但重複的數字不是第乙個數字和最後乙個數字
[testmethod]
public
void
getminnumtest3()
;assert.areequal(program.getmin(array), 1);
}
//(5)單調公升序陣列,旋轉0個元素,也就是單調公升序陣列本身有重複的數字,並且重複的數字剛好是第乙個數字和最後乙個數字
[testmethod]
public
void
getminnumtest4()
;assert.areequal(program.getmin(array), 0);
}
//(6)陣列中只有乙個數字單調公升序陣列,旋轉0個元素,也就是單調公升序陣列本身
[testmethod]
public
void
getminnumtest5()
;assert.areequal(program.getmin(array), 1);
}
//(7)魯棒性測試:輸入null陣列中只有乙個數字
[testmethod]
public
void
getminnumtest6()
;assert.areequal(program.getmin(array), 2);
}
//單元測試的結果如下圖所示:魯棒性測試:輸入null
[testmethod]
public
void
getminnumtest7()
對於getmin方法編寫的單元測試的**覆蓋率已達到了100%:
出處:
《劍指offer》面試題7 旋轉陣列的最小數字
把乙個陣列最開始的若干個元素搬到陣列的末尾,我們稱之為陣列的旋轉。輸入乙個非遞減排序的陣列的乙個旋轉,輸出旋轉陣列的最小元素。例如陣列為的乙個旋轉,該陣列的最小值為1。note 給出的所有元素都大於0,若陣列大小為0,請返回0。1.如果使用暴力查詢法,則可以迅速求解,但是使用這種方法絕對不可能通過面...
劍指offer 面試題11 旋轉陣列的最小數字
完整 位址 把乙個陣列最開始的若干個元素搬到陣列的末尾,我們稱之為陣列的旋轉。輸入乙個非遞減排序的陣列的乙個旋轉,輸出旋轉陣列的最小元素。例如陣列為的乙個旋轉,該陣列的最小值為1。note 給出的所有元素都大於0,若陣列大小為0,請返回0。這道題目相對前面的比較複雜,坑比較多 此時用二分法解決,mi...
劍指Offer面試題11 旋轉陣列的最小數字
把乙個陣列最開始的若干個元素搬到陣列的末尾,我們稱之為陣列的旋轉。輸入乙個非減排序的陣列的乙個旋轉,輸出旋轉陣列的最小元素。例如陣列為的乙個旋轉,該陣列的最小值為1。note 給出的所有元素都大於0,若陣列大小為0,請返回0。牛客網ac class solution int left 0,right...