一、時間復雜度、空間復雜度
時間復雜度:用來評估算法運行效率的一個東西,用O()來表示
舉例時間復雜度計算:
print('Hello World') O(1)
for i in range(n): #n次循環 print('Hello World') O(n)
for i in range(n): for j in range(n): #兩個n嵌套循環 print('Hello World') O(n²)
以下這些代碼時間復雜度呢?
print('Hello World') print('Hello Python') #看着是三個運行,但是也是O(1) print(‘Hello Algorithm’) O(1)
for i in range(n): print('Hello World’) for j in range(n): print('Hello World') O(n²)
下面這個代碼的時間復雜度呢?
while n > 1: print(n) n = n // 2 2^6=64 log2^64=6 所以時間復雜度是:O(log2^n),也可以當做O(logn)
時間復雜度小結:
1.時間復雜度是用來估計算法運行時間的一個式子(單位)。 2.一般來說,時間復雜度高的算法比復雜度低的算法慢。
如何一眼判斷時間復雜度?
1.循環減半的過程:O(logn) 2.幾次循環就是n的幾次方的復雜度
空間復雜度:用來評估算法內存占用大小的一個式子。
采用:空間換時間
二、列表排序
列表排序:將無序列表變為有序列表
輸入:無序列表
輸出:有序列表
幾種常見的排序算法:冒泡排序,選擇排序,插入排序,快速排序等
1.冒泡排序
思路:
1.有一個無序列表,比較列表兩個相鄰的數,如果前邊的比后邊的大,就交換它們兩個
2.對每一對相鄰元素做同樣的工作,從開始第一對到結尾的最后一對,這樣最后的元素就是值最大的。
3.重復上面的步驟,除了最后一個
所以我們要寫兩個for循環:
第一個for循環作用:控制排序的輪數
第二個for循環作用:控制每一輪里的每一個比較
冒泡排序代碼如下:
li=[4,1,3,6,7,9,2,5,8] def Bubble_sort(li): for i in range(len(li)-1): for j in range(len(li)-1-i): if li[j] > li[j+1]: li[j], li[j+1] = li[j+1], li[j] print(li) Bubble_sort(li) #排序結果 [1, 2, 3, 4, 5, 6, 7, 8, 9]
冒泡排序的時間復雜度:O(n²),空間復雜度O(1)
冒泡排序優化:
如果冒泡排序中執行一趟而沒有交換,則列表已經是有序狀態,可以直接結束算法。
2.選擇排序
思路:
1.一趟遍歷記錄最小的數,放到第一個位置。
2.再一趟遍歷記錄剩余列表中最小的數,繼續放置
可以理解為:取列表索引為0的值,和后面位置的元素比較,索引為0的值大於其他位置的值就調換位置。索引0的值和所有元素比較完了,再索引1的值和后面元素依次比較,索引1的值大於其他位置的值就調換位置,以此類推,從小到大排序。
選擇排序代碼示例:
li=[4,3,6,1,7,9,2,5,8] def select_sort(li): for i in range(len(li)): minLoc = i ###i = 0 for j in range(i+1, len(li)): if li[j] < li[minLoc]: li[j], li[minLoc] = li[minLoc], li[j] print(li) select_sort(li) #結果[1, 2, 3, 4, 5, 6, 7, 8, 9]
選擇排序的時間復雜度:O(n²),空間復雜度O(1)
3.插入排序
思路:類似於斗地主插牌
1.列表被分為有序區和無序區兩個部分,最初有序區只有一個元素,假如抽取第一個元素
2.每次從無序區選擇一個元素,插入到有序區的位置,和有序區的值一一比較,直到無序區變空
插入排序代碼示例:
li=[4,3,6,1,7,9,2,5,8] def insert_sort(li): for i in range(1, len(li)): tmp = li[i] j = i - 1 while j >=0 and li[j] > tmp: li[j+1] = li[j] j = j - 1 li[j+1] = tmp print(li) insert_sort(li) #結果 [1, 2, 3, 4, 5, 6, 7, 8, 9]
插入排序時間復雜度:O(n²),空間復雜度O(1)
4.快速排序
好寫的排序算法里最快的 ,快的排序算法里最好寫的(寫法比之前的幾種復雜一點)
思路:
1.從數列中取出一個元素(一般取第一個元素),稱為"基准"
2.寫一個函數重新排序數列,所有元素比基准小的都放在基准左邊,所有元素比基准大的都放在右邊,相同的數到同一邊。在這個分區退出之后,該基准就處於數列的中間位置。
3.再寫一個函數,使用遞歸把小於基准值元素的子數列和大於基准值元素的子數列排序。遞歸的最底部情形,是數列的大小是零或一,也就是永遠都已經被排序好了。雖然一直遞歸下去,但是這個算法總會退出,因為在每次的迭代中,它至少會把一個元素擺到它最后的位置去。
快速排序關鍵點:1.整理,2.遞歸
快速排序代碼示例:
li=[4,3,6,1,7,9,2,5,8] #第一個函數,根據基准分區 def partition(li, left, right): tmp = li[left] while left < right: while left < right and li[right] >= tmp: right = right - 1 li[left] = li[right] while left < right and li[left] <= tmp: left = left + 1 li[right] = li[left] li[left] = tmp return left #第二個函數使用迭代 def quick_sort(li, left, right): if left < right: mid = partition(li, left, right) quick_sort(li, left, mid-1) quick_sort(li, mid+1, right) print(li) quick_sort(li, 0, len(li)-1) #結果:[1, 2, 3, 4, 5, 6, 7, 8, 9]
快速排序時間復雜度:O(nlogn),空間復雜度:O(logn)
未完。。。。