最長等差數列;及子序列分析

紫鳳發表於2013-09-16

今日面試題:最長等差數列

給定未排序的陣列,請給出方法找到最長的等差數列。

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

子序列分析

原題

給定長度為n的整數數列:a0,a1,..,an-1,以及整數S。這個數列會有連續的子序列的整數總和大於S的,求這些數列中,最小的長度。

分析

如果只是像題目這樣的描述,沒有強調正數,可以採用O(n^2)的方法。但是,很多同學在討論的時候,指出瞭如果是正數,解法將會有什麼樣的變化。這個很好。不考慮正負的O(n^2)的方法,這裡不詳細說了,我們來討論,當數列中都是正數的情況。

介紹一個利用排序+二分的方法。對於子序列ai...at,子序列和s=ai+...+at=sum[t]-sum[i-1]。sum[t]表示數列a0...at的和。那麼,陣列sum天然就是遞增的,可以進行二分查詢。 那麼如何進行二分查詢呢?對於陣列sum,遍歷找到第一個k,sum[k]>S,二分查詢k前面的某一個j,j是sum[k]-sum[j]>S裡最大的一個,則k-j是最小的。依次遍歷完陣列。 可以得到最小的長度,整體的時間複雜度O(nlogn),空間複雜度為O(n)。 是否有更快的方法呢?從以上兩個方法,我們可以有如下的觀察:

  • a0...at>S,則a0...at+1無需再考慮

  • 對於a0...at>S,只需嘗試a1...at是否>S,如果大於S,則更新最短長度。

  • 如果不大於S,大於S的只可能是a1...atat+1等。

鑑於以上的觀察,我們有如下的演算法:設定索引i,j指向第一個整數:

1. ++j,直到sum[j]-sum[i]>S,這裡不需要額外儲存sum,為了方便說明。記錄子序列長度

2. ++i,如果sum[j]-sum[i]>S,更新最小子序列長度。直到sum[j]-sum[i]<=S。

3. ++j,直到sum[j]-sum[i]>S。重複上面的兩步,直到陣列遍歷完畢。

整個演算法的時間複雜度為O(n)。下面我們做一個示例陣列為{5,1,3,5,10,7,4,9,2,8},S=10,i=j=0開始

1. 當j=3時,和為14>10,則更新最小長度為4

2. 對i進行遞增操作,和為9<10,不滿足條件。對j進行遞增

3. 當i=1,j=4時,和為19>10,長度為4,不更新最小長度。遞增i,直到i=3,此時和15>10,更新最小長度為2,

4. 依次類推

最終得到最小長度為2.

【分析完畢】

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

相關文章