演算法基礎第二章O N logN 的排序

2021-09-25 03:02:56 字數 1324 閱讀 7262

先排序左邊,再排序右邊,最後通過乙個輔助陣列merge

利用master公式估計時間複雜度:

t(n) = 2*t(n/2) + o(n)

a = 2, b=2, d=1

時間複雜度為:o(n*logn),額外空間複雜度:o(n)

拓展:小和問題

陣列中求每個數左邊比他小的數的和。

普通解法:o(n^2)

歸併解法:在merge和sort的過程中發現左側數比右側數小就把 「小和」 加上

逆序對問題

左邊的數比右邊的數小

陣列實現的完全二叉樹(從左到右依次變滿)結構

節點個數是n, 高度是logn.
i 位置的左孩子是2i+1, 右孩子是2i+2, 父節點是 (i-1)/2

根節點為0
方法

add (member)

新加入的資料放到最後位置,並依次和父節點比較大小, 若比父節點大則交換兩者位置.

intgetmax()

輸出最大值,並更新最大堆

返回最大值後, 把最後乙個數放到根節點, 然後和最大子節點比較大小並調整. heapify()

擴容一次擴大一倍

先滿足0~0範圍是堆,然後依次新增數字,逐漸建立堆o(n*logn)

如果一次性得到全部資料, 從下往上逐漸保證每個子樹調整成大根堆的時間複雜度更低 o(n).

每次把根節點和最後乙個節點交換, 並將heapsize減1

將新的根節點向下heapify到目標位置

重複2,3過程,直到heapsize等於0

時間複雜度: o(n*logn)

例題:

乙個幾乎有序的陣列, (每個元素移動距離不超過k, k比較小) 選擇最佳排序方法.

利用乙個大小為k的最小堆, 每次彈出最小的放到0位置(1,2,3…), 再把後乙個(k+1)數放進堆裡, 周而復始.

o(n*logk) -> o(n)

預設為小根堆, 若需要大根堆, 儲存成相反數 (加負號)
import heapq

heap = #建立乙個常見的堆

item = heap[0]#檢視堆中最小的值,不彈出

heapify(x)#以線性時間將乙個列表轉為堆

merge()#將多個堆進行合併

nlargest(n , iterbale, key=none)從堆中找出做大的n個數,key的作用和sorted( )方法裡面的key類似,用列表元素的某個屬性和函式作為關鍵字

第二章 演算法基礎

引言 演算法導論 在本章將向我們介紹乙個演算法設計和分析框架,在後續的章節也將在這個框架的基礎上來分許演算法。名詞解釋 1 偽 偽 就是以最清晰 最簡潔的表示方法來說明演算法,而忽略資料抽象 模組性和錯誤處理的問題 2 迴圈不變式 每次迴圈從陣列a中取出第j個元素插入有序數列a 1 j 1 然後遞增...

第二章 演算法基礎

2.1 插入排序 insertion sort 時間複雜度 o n 對於少量元素的排序,是乙個有效的演算法。為什麼叫插入排序呢?可以模擬撲克牌整牌 將未排序的數字通過遍歷插入到已排好序的數字中的對應位置 如何實現呢 num j 1 key 插入 for int i 1 i n i printf n ...

第二章 演算法基礎

本章首先講了插入排序演算法,然後分析了插入排序演算法的時間複雜性,引出了分治法的設計思想,分析了分治演算法。1.插入排序 插入排序採用了增量演算法 在排序子陣列a 1.j 1 後,將單個元素a j 插入到子陣列的適當位置,產生排序好的子陣列a 1.j 1 package sort 23 import...