求最長等差數列

以下內容轉自:微信:待字閨中


原題

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


分析

題目描述比較簡單,但是有一個問題我們需要首先搞清楚:等差數列中的數字,是否要和原始數組中的順序一致。題目中,並沒有說明,這個就需要大家在面試的過程中和面試官進行交流。我們在這裏對兩種情況都進行討論


保證數字的順序

等差數列是要求相鄰兩個元素之間的差是相同的。那我們可以記錄下來數組中任意兩個數的差,並且記錄下來。對於數組A,記錄A[j]-A[i],其中 i<j。這裏採用hashmap來記錄,key就是A[j]-A[i],value是所有差等於的A[j]-A[i]的(i,j)位置對。構造 hashmap的過程是O(n^2)的。然後,遍歷hashmap的每一個value,對位置對按照起始位置進行排序,再進行一次遍歷就可以得到最長的等 差數列。如下面的數組:{5,4,3,4,7,8}

構造hashmap如下:

  • -1=>(0,1)(1,2)

  • 1=>(2,3)(4,5)

  • 3=>(3,4)

上面已經排好序,對於第一個,找到等差數列0,1,2對應數字誒5,4,3.第二個,3和4位置沒有連起來,不夠成等差數列。方法平均時間複雜度爲O(n^2),空間複雜度爲O(n^2).


無需保證數字的順序

不需要保證數字的順序與原來數組一致,如何找到最長的等差數列呢?原來的數組是無序的,我們先對數組進行排序,最終的一定是排序之後序列的子序列。然後,我們採用動態規劃的方法解決這個問題。

我們假設dp[i][j]表示以A[i]A[j]開始的數列的長度,dp[i][j]如何表示呢?dp[i][j]=dp[j][k]+1,當 A[j]-A[i]=A[k]-A[j],及A[k]+A[i]=2*A[j]。根據dp[i][j]的定義,我們知道dp[x][n-1]=2,也就是 最後一列是2,數列只有A[x]和A[n-1]兩個元素。首先,j從n-2,開始向前遍歷,對於每一個,找到i和k,滿足 A[k]+A[i]=2*A[j],則有dp[i][j]=dp[j][k]+1,若沒有,則dp[i][j]就爲2.

這裏找i和k,有一個小技巧,如下:初始i=j-1,k=j+1,然後分別向兩邊遍歷,如果A[k]+A[i]2*A[j]則i--。大家還是參考代碼吧:


【分析完畢】


其實,兩種情況最終都是求最長的等差序列,只是第一種情況是在無序的序列中求,第二種情況是在遞增的序列中求。

所以,第二種情況比第一種情況的數據更嚴格,理論上算法也可以更優。實際上卻確實如此。


第一種情況給出的解法,作者雖說“方法平均時間複雜度爲O(n^2),空間複雜度爲O(n^2).”,但是時間複雜度爲O(n^2)還是值得商榷的(如果再增加空間複雜度,就沒有異議了)。


第二種情況給出的解法,時間複雜度爲O(n^2),空間複雜度爲O(n^2),沒有異議,而且很很巧妙,利用了遞增的性質。另外,@曹鵬博士 推薦了一篇論文http://www.cs.uiuc.edu/~jeffe/pubs/pdf/arith.pdf 據說時間複雜度可以更小一些。







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章