我閱讀的演算法書籍是李煜東的《演算法競賽高階指南》。翻開目錄,我第一眼關注到的就是資料結構高階這一類,畢竟上學期剛學資料結構,相信這一塊是能夠最快接受的知識點。
第一節講的是並查集,這還是比較簡單。並查集就分為兩步,第一步是查詢乙個元素屬於哪個集合,第二步是把兩個小集合合併成乙個大集合。那麼合併集合的依據是什麼呢?如果每個集合都選出乙個「代表」元素,即該集合內的每乙個元素查詢後的結果是這個「代表」。顯然每乙個「代表」的查詢結果是自己,而合併,就是讓其中乙個集合的「代表」成為另乙個集合的「代表」的「代表」,這樣再更新其他成員的「代表」,這樣合併就完成了。用一句通俗的話講就是「我大哥的大哥就是我的大哥」,只是這樣原來的「大哥」變成了和自己平級的存在了。就和它的名字一樣,就是查詢兩個個集合的「代表」,再通過改變「代表」的指向關係,使兩個集合就可以合成為乙個。
實際上,我們在查詢過程中只關心「代表」是什麼,因此我們可以在查詢操作的時候將訪問過的每個點都指向「代表」,這樣的方法叫做路徑壓縮,單次操作複雜度為o(logn)。
那麼並查集可以拿來解決哪些問題呢?比如說需要你去區分陣營,區分敵人和朋友的時候,就可以用並查集,畢竟我朋友的朋友也是我的朋友。還有就是可以用並查集來判斷無向圖是否有迴路,通過無向圖的一條條路將乙個個單獨的點新增進集合的時候,如果發現某一條路上的兩個點的「代表」是同乙個,那麼這個無向圖就是有迴路。
後面一講是樹狀陣列,它的功能主要就是查詢字首和,演算法的複雜度更是只有o(logn)。這裡我看了好久不知道為什麼要用x&(-x)。直到理解了後面的圖。如果說原陣列為an,對應的樹狀陣列是cn。通過後面的圖我們可以發現:
c[1] = a[1];
c[2] = a[1] + a[2];
c[3] = a[3];
c[4] = a[1] + a[2] + a[3] + a[4];
c[5] = a[5];
c[6] = a[5] + a[6];
c[7] = a[7];
c[8] = a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8];
再c[i] = a[i - 2k+1] + a[i - 2k+2] + … + a[i];k為i的二進位制中從最低位到高位連續0的長度,而要找出這個0的長度,就要用到i&(-i)。當然直接用c[i]不一定是i的字首和,所以需要i-=i&(-i)後再加上c[i]補齊前面漏下的項。比如說i=5,c[5]=a[5];i-=i&(-i)後i=4,c[4] = a[1] + a[2] + a[3] + a[4];i-=i&(-i)後i=0,結束,這時ans=c[5]+c[4]=a[1]+a[2]+a[3]+a[4]+a[5].然後查詢區間[l,r]中所有數的和,只需要r的字首和減去(l-1)的字首和。
樹狀陣列還有乙個功能就是單點更新,實際操作就是:如果a[i]更新了,通過i+=i&(-i)將c陣列中所有包含a[i]的元素進行更新。
演算法分析與實踐 作業13 讀書筆記
演算法競賽高階指南 讀書筆記 在學習了演算法設計與分析基礎這門課後,我還翻閱了 演算法競賽高階指南 這本書,這本書根據ccf noi資訊學奧利匹克競賽涉及的知識體系進行編寫,對計算機程式設計的基本技能 資料結構與演算法進行了深入的講解。我覺得通過這本書,我了解到的東西還是比較豐富的。比如字典樹的概念...
演算法設計與分析 作業13 讀書筆記
啊哈!演算法 讀書筆記 啊哈!演算法 這本書中的演算法舉例貼近生活,語言詼諧幽默,不會讓人產生枯燥感,並配有很多幽默的插圖。演算法講解通俗易懂,並配有詳細c語言 和注釋,是一本適合初學者學習以及借鑑的演算法書籍。由於時間有限,我簡單花了一些時間閱讀了其中的排序板塊,各種排序演算法層出不窮,一直都是困...
演算法分析與設計 作業13 讀書筆記
我在知乎上找有關演算法書的推薦,偶然間找到了這本 演算法導論 雖然我沒有完全看完,但我還是獲得了一些收穫。通過閱讀這本書使我更深刻地了解了演算法思想。我了解了書中有關動態規劃 貪心演算法 攤還分析 b樹 斐波那契堆等內容。初次接觸演算法,我感到還是有點困難,尤其是在演算法分析這一塊。一般來說學習演算...