程式員面試題精選100題(42)-旋轉數組的最小元素[演算法]_劍指Offer

來源:互聯網
上載者:User

題目:把一個數組最開始的若干個元素搬到數組的末尾,我們稱之為數組的旋轉。輸入一個排好序的數組的一個旋轉,輸出旋轉數組的最小元素。例如數組{3, 4, 5, 1, 2}為{1, 2, 3, 4, 5}的一個旋轉,該數組的最小值為1。

         分析:這道題最直觀的解法並不難。從頭到尾遍曆數組一次,就能找出最小的元素,時間複雜度顯然是O(N)。但這個思路沒有利用輸入數組的特性,我們應該能找到更好的解法。

         我們注意到旋轉之後的數組實際上可以劃分為兩個排序的子數組,而且前面的子數組的元素都大於或者等於後面子數組的元素。我們還可以注意到最小的元素剛好是這兩個子數組的分界線。我們試著用二元尋找法的思路在尋找這個最小的元素。

         首先我們用兩個指標,分別指向數組的第一個元素和最後一個元素。按照題目旋轉的規則,第一個元素應該是大於或者等於最後一個元素的(這其實不完全對,還有特例。後面再討論特例)。

接著我們得到處在數組中間的元素。如果該中間元素位於前面的遞增子數組,那麼它應該大於或者等於第一個指標指向的元素。此時數組中最小的元素應該位於該中間元素的後面。我們可以把第一指標指向該中間元素,這樣可以縮小尋找的範圍。同樣,如果中間元素位於後面的遞增子數組,那麼它應該小於或者等於第二個指標指向的元素。此時該數組中最小的元素應該位於該中間元素的前面。我們可以把第二個指標指向該中間元素,這樣同樣可以縮小尋找的範圍。我們接著再用更新之後的兩個指標,去得到和比較新的中間元素,迴圈下去。

按照上述的思路,我們的第一個指標總是指向前面遞增數組的元素,而第二個指標總是指向後面遞增數組的元素。最後第一個指標將指向前面子數組的最後一個元素,而第二個指標會指向後面子數組的第一個元素。也就是它們最終會指向兩個相鄰的元素,而第二個指標指向的剛好是最小的元素。這就是迴圈結束的條件。

基於這個思路,我們可以寫出如下代碼:

// Get the minimum number of a roatation of a sorted arrayint Min(int *numbers, int length){    if(numbers == 0 || length <= 0)        throw new std::exception("Invalid parameters");     int index1 = 0;    int index2 = length - 1;    int indexMid = index1;    while(numbers[index1] >= numbers[index2])    {        if(index2 - index1 == 1)        {            indexMid = index2;            break;        }         indexMid = (index1 + index2) / 2;        if(numbers[indexMid] >= numbers[index1])            index1 = indexMid;        else if(numbers[indexMid] <= numbers[index2])            index2 = indexMid;    }     return numbers[indexMid];}


由於我們每次都把尋找的範圍縮小一半,該演算法的時間複雜度是O(logN)

值得注意的是,如果在面試現場寫代碼,通常我們需要用一些測試案例來驗證代碼是不是正確的,我們在驗證的時候盡量能考慮全面些。像這道題,我們出來最簡單測試案例之外,我們至少還需要考慮如下的情況:

1.              把數組前面的0個元素從最前面搬到最後面,也就是原數組不做改動,根據題目的規則這也是一個旋轉,此時數組的第一個元素是大於小於或者等於最後一個元素的;

2.              排好序的數組中有可能有相等的元素,我們特別需要注意兩種情況。一是旋轉之後的數組中,第一個元素和最後一個元素是相等的;另外一種情況是最小的元素在數組中重複出現

3.              在前面的代碼中,如果輸入的數組不是一個排序數組的旋轉,那將陷入死迴圈。因此我們需要跟面試官討論是不是需要判斷數組的有效性。在面試的時候,面試官討論如何驗證輸入的有效性,能顯示我們思維的嚴密性。本文假設在調用函數Min之前,已經驗證過輸入的有效性了。

最後需要指出的是,如果輸入的數組指標是非法指標,我們是用異常來做錯誤處理。這是因為在這種情況下,如果我們用return來結束該函數,返回任何數字都不是正確的。關於無效輸入時的函數如何返回錯誤資訊並結束,本部落格第17題有更詳細的討論,可以參考。

 

本文已經收錄到《劍指Offer——名企面試官精講典型編程題》一書中,有改動,書中的分析講解更加詳細。歡迎關注。

本題已被九度Online Judge系統收錄,歡迎讀者移步到http://ac.jobdu.com/hhtproblems.php線上測試自己的代碼。


博主何海濤對本部落格文章享有著作權。網路轉載請註明出處http://zhedahht.blog.163.com/。整理出版物請和作者聯絡。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.