找陣列的波谷;及巧妙排序的分析

紫鳳發表於2013-07-26

今日面試題:找陣列的波谷

一個陣列A[1...n],滿足A[1]>=A[2], A[n] >= A[n-1]。A[i]被成為波谷,意味著:A[i-1] >= A[i] <= A[i+1]。請給出一個演算法,找到陣列中的一個波谷。O(n)的方法,是很直接,有更快的方法麼?

=========================

巧妙排序分析:

原題

排序只有1,2,3三個元素的陣列,不能統計1,2,3的個數。

分析

這個題目,儘管也是排序,但卻不能使用快速排序的方法。只有三個元素,如果時間複雜度仍舊是O(nlogn),顯然不是最好的。那就可以使用線性的排序演算法,例如計數排序,可是題目中要求,不能夠對1,2,3進行統計個數。那該如何處理呢?請大家看下面的方法,我們首先通過例子來說明:

2 1 1 3 3 2
p1 p2 p3

假設,我們有三個指標:p1、p2、p3.p1從左側開始,指向第一個非1的數字;p3從右側開始,指向第一個非3的數字。p2從p1開始遍歷,如果是2,p2繼續遍歷,直到p2遇到1或者3:

如果遇到1,則和p1進行交換,然後p1向右,指向第一個非1的數字

如果遇到3,則和p3進行交換,然後p3向左,指向第一個非3的數字

1 2 1 3 3 2
p1,p2 p3

交換之後,p2繼續從p1開始,如果是2繼續遍歷,如果是1或者3,重複上面的步驟,所得如下:

1 1 2 3 3 2
p1,p2 p3

根據上面的方法繼續下去

1 1 2 2 3 3
p1 p3 p2

p2在p3右側,演算法結束。

總結一下上面的演算法:

p1從左側開始,指向第一個非1的數字;p3從右側開始,指向第一個非3的數字。

p2從p1開始遍歷,如果是2,p2繼續遍歷,直到p2遇到1或者3

如果遇到1,則和p1進行交換,然後p1向右,指向第一個非1的數字

如果遇到3,則和p3進行交換,然後p3向左,指向第一個非3的數字

重複上面的步驟,直到p2在p3的右側結束。

基於快排劃分的思路

上面的思路,是針對三個數的,如果有更多的數,怎麼處理呢?比如,4個,5個等等。下面根據快速的排序的啟發,介紹一種演算法,儘管在處理三個數的時候,比較次數會多些,但,具有很好的通用性。

思路來自快排的劃分部分,快排的劃分部分:給定pivot,然後將資料劃分為<=pivot和>pivot兩部分。這樣,三個數字時,需要兩次劃分:

第一次,用1作為pivot,劃分1到最左邊;

第二次,用2作為pivot,劃分2到左邊,則得到整體的排序。

最巧妙的思路

我們將1,2,3,替換為互質的2,3,5,得到如下:

2 1 1 3 3 2
3 2 2 5 5 3

之後,乘起來得到的900.這900裡,除以2,有多少個2,就有多少個1;然後除以3,有多少個3,就有多少個3對應的2;然後除以5,有多少個5,就有多少個5對應的3。這是如何保證的呢?因為2,3,5是互質的。

如下:

被除數 除數 餘數 排序結果
900 2 450 0 1
450 2 225 0 1
225 2 112 1 2嘗試結束,嘗試3
225 3 75 0 2
75 3 25 0 2
25 3 8 1 3嘗試結束,嘗試5
25 5 5 0 3
5 5 1 0 3
1 5 1 1 全部結束

最終結果為112233.上面的這種思路,實際上是計數的一種變種。沒有直接的技術,那自然就是可以的。

【分析完畢】

本文來自微信:待字閨中,2013-07-22釋出,原創@陳利人 ,歡迎大家繼續關注微信公眾賬號“待字閨中”。

相關文章