面試題 5 旋轉陣列中的最小數字

2021-08-15 04:16:14 字數 2479 閱讀 3480

我想最為直接的方法就是從頭到尾,遍歷一次,那麼這樣的時間複雜度為 o(n);通過這樣的方法得到的結果,面試官雖然不能算我們錯,但也絕對不會給我們高分。

我們首先要注意,旋轉陣列的特點,經過旋轉,其實就是把原來有序的陣列,分成兩個有序的序列,就像題幹中的 ,前面的 3, 4, 5 是乙個遞增的序列,後面的 1, 2 也是乙個遞增的序列,那麼我們該如何利用這樣的特性,去「高效」 (存在特例)的完成這道題呢???

我們想想二分法是否能高效的解決呢?

首先,我們使用兩個指標,乙個指向陣列的開始,乙個指向陣列的末尾,那麼一般情況下(存在特例)陣列的首元素 會 大於陣列的末尾元素。當 中間元素 大於 陣列首元素 時,中間元素肯定在前面的遞增序列中,當 中間元素 小於陣列末尾元素時,中間元素肯定在後面的遞增序列中。這樣的話,我們就可以縮小查詢的範圍。

根據這種情況,我們可以寫出如下的**:

圖(1)原因:這個遞增的陣列,經過旋轉後,形成了 兩個各自有序的序列(為了之後方便說明,就稱為 左陣列 和 右陣列),左陣列的最前面元素 是這個陣列中最小的,右陣列的最前面元素也是這個陣列中最小的。因此當 head 從頭往後遍歷時,當一直都滿足 」 arr[head] >= arr[tail] 」時,一旦 head 和 tail 相遇時,tail 所指向的就是最小的數了。

圖(2)

圖(3)

但是這樣就完美了嗎?之前提到的特例,就是這個缺陷所在,什麼特例呢?看一下下面這個序列

此時,head 指向的 與 tail 指向的 與 middle 指向的元素大小 一樣大,你還能判斷 midlle 在左陣列 和 右陣列嗎(尷尬)?

遇到這樣的情況,只能從頭開始遍歷了(哈哈哈)

#include 

using

namespace

std;

int minorder(int arr,int head,int tail)

return result;

}int mymin(int arr, int len)

middle = (head + tail) / 2;

// 當出現 陣列首元素 和 尾元素 都等於 中間元素時,呼叫另乙個函式

if (arr[middle] == arr[head] && arr[head] == arr[tail])

return minorder(arr, head, tail);

if (arr[middle] >= arr[head])

head = middle;

else

if (arr[middle] <= arr[tail])

tail = middle;

}return arr[middle];

}int main()

; int length = sizeof(array) / sizeof(array[0]);

int min = mymin(array, length);

cout

<< "min:"

<< min << endl;

return

0;}

結果:

當你向面試官寫出這樣的**,朋友, 你被錄用了。

面試題 旋轉陣列的最小數字

題目 把乙個陣列最開始的若干個元素搬到陣列的末尾,我們稱之為陣列的旋轉。輸入乙個遞增排序的陣列的乙個旋轉,輸出旋轉陣列的最小元素。例如陣列為的乙個旋轉,該陣列的最小值為1。解法 順序查詢即可,時間複雜度為 利用二分查詢的思想,大部分情況旋轉後陣列最小值左邊數值為最大,利用前後指標的方法找到最小值,此...

面試題8 旋轉陣列中的最小數字

旋轉陣列的特點 1 遞增排序的陣列旋轉之後的陣列可劃分為兩個排序的子陣列 2 前面的子陣列的元素都大於或等於後面子陣列的元素 3 最小的元素剛好是兩個子陣列的分界線 4 旋轉陣列在一定程度上是有序的 在有序的陣列中可以用二分查詢實現o logn 的查詢,我們也可用二分查詢的思想尋找旋轉陣列的最小數字...

面試題8 旋轉陣列的最小數字

題目描述 把乙個陣列最開始的若干個元素搬到陣列的末尾,我們稱之為陣列的旋轉。輸入乙個遞增排序的陣列的乙個旋轉,輸出旋轉陣列的最小元素。例如陣列為的乙個旋轉,該陣列的最小值為1。輸入 輸入可能包含多個測試樣例,對於每個測試案例,輸入的第一行為乙個整數n 1 n 1000000 代表旋轉陣列的元素個數。...