在《程式設計珠璣》第八章,作者提出一道演算法題:
程式描述:
輸入是乙個具有n個浮點數字的向量x: 其輸出是在輸入的任何相鄰子向量中找出的最大和。
例如,輸入如下10個元素:
31 -41 59 26 -53 58 97 -93 -23 84
返回 x[2..6]的總和,或為187
作者分別給出了三次演算法o(n^3),兩個二次演算法o(n^2),分治演算法o(n logn )和掃瞄演算法o(n)。
我對該問題作了研究後,給出自己的一種解法。
考慮陣列 x[ n ],我們新開闢乙個陣列sumx[ n + 1 ],其中sumx[ 0 ] = 0, 而 sumx[ i ] 為 x[ 0..i-1 ] 的和。
這樣,對於 x[ i..j ]的和,有 sum( x[ i..j ] ) = sumx[ j+1 ] - sumx[ i ].
對於陣列sumx, 假設最大值為 sumx[ po**ax ], 最小值為 sumx[ po**in ],下面分三種情況:
1. po**in < po**ax,也即最小值在最大值左邊,我們可以肯定 x[ po**in..po**ax-1 ] 就是所要求的總和。
否則,若x[ i..j ]是所要求的總和,且 i != po**in或 j != po**ax,
則有sum( x[ i..j ] ) <= sum( x[ po**in, j ] ) <= sum( x[ po**in, po**ax ] )
或sum( x[ i..j ] ) <= sum( x[ i, po**ax ] ) <= sum( x[ po**in, po**ax ] )
上面兩不等式至少有乙個嚴格小於,所以sum( x[ i..j ] ) < sum( x[ po**in, po**ax ] )
由上可知,這種情況中返回結果 sumx[ po**ax ] - sumx[ po**in ]
2. po**in == po**ax,說明除了 x[ po**in ]外,其餘x[ i ] 全為0
又由於sumx[ 0 ] = 0,所以 sumx[ po**ax ] > 0
所以 x[ po**ax - 1 ]是所要求的總和
這種情況中返回結果 sumx[ po**ax ],也就是 x[ po**ax-1 ] 乙個元素
3.po**in > po**ax
這種情況比較複雜,我們可以把sumx分為三部分:
a)sumx[ 0 ]..sumx[ po**ax ]; b)sumx[ po**ax + 1 ] ... sumx[ po**in - 1 ], c)sumx[ po**in ].. sumx[ n + 1 ].
我們可以肯定,要找出的x[ i..j-1 ],也可以認為是sumx[ i],sumx[j ]必在同乙個小部分中。
否則,若 0 <= i <= po**ax 而 po**ax < j
則sum( x[ i..j-1 ] ) = sumx[ j ] - sumx[ i ] < sumx[ po**ax ] - sumx[ i ]。
對於其他情況,也可以同樣證明。
於是我們可以分別對陣列a,b,c處理,找出最大和。
對陣列a,找出最小值sumx[ po**in1 ],必有po**in1 < po**ax,
於是結果 tmpmax1 = sumx[ po**ax ] - sumx[ po**in1 ]
對陣列c,找出最大值sumx[ po**ax3 ],必有po**in < po**ax3,
於是結果 tmpmax3 = sumx[ po**ax3 ] - sumx[ po**in ]
對陣列b,這是乙個比開始問題規模更小的子問題,可再迭代處理,得到結果tmpmax2
這種情況中返回結果 tmpmax1, tmpmax2, tmpmax3中最大值
這種演算法在最優情況下(po**in <= po**ax)可看作一線性演算法,執行時間o(n)
在最壞情況下(每次處理均有po**ax = 0, po**in = 陣列索引最大值,每個子問題規模減2),
這時可看作二次演算法,執行時間o(n^2)
使用隨機數除錯,發現大部分情況執行時間在o( n logn ) 與 o( n^2 )之間。
測試結果:
n=10 n*logn=23 n*sqrtn=31 n^2=100 程式執行次數:27
n=100 n*logn=460 n*sqrtn=1000 n^2=10000 程式執行次數:404
n=1000 n*logn=6907 n*sqrtn=31622 n^2=1000000 程式執行次數:13009
n=10000 n*logn=92103 n*sqrtn=1000000 n^2=100000000 程式執行次數:683867
程式設計珠璣讀後感
第二章則又提出了三個問題,提到了二分查詢的廣泛應用,打破了對二分查詢的狹隘理解,以及一種旋轉向量的巧妙演算法 感覺用到了數論的一些知識 感覺最巧妙的還是對與查詢字典中所有變形詞集的巧妙解法,其採用利用簽名歸類的方法,然後對簽名進行排序,我之前從來沒有遇到過,感覺十分新奇。第三章講了一些資料結構的技巧...
《C程式設計》讀後感
c程式設計 讀後感 網上很多人評價這書不高,其實從內心裡講,是這本書帶領我入門的。我說的是譚浩強先生的書。這本書講得很細,而且知識的銜接也做得很好。我以這本書為重點,再以其它的c語言教程為輔,終於算是入了c語言的門。如果能讓我再從頭學習的話,我一定是認真的讀這本教材,再把c的標準庫的原始碼作為閱讀材...
《程式設計實踐》讀後感
程式設計實踐 讀後感 昨天晚上讀這本書,重點讀資料結構這一章,也許是因為讀gawk101原始碼有一段時間,在重讀時,感覺作者寫得真好。我重點放在書中的 上,發現那些 寫得像珍珠一樣,真是漂亮。作者寫了鍊錶,然後再寫乙個遍歷鍊錶的函式,因為遍歷鍊錶時,可能是要列印,可能是要統計元素個數,可能是要找某個...