echarts地圖展示
阿新 • • 發佈:2021-06-17
演算法與資料結構是面試考察的重中之重,也是日後刷題時需要著重訓練的部分。
簡單的總結一下,大約有這些內容:
演算法 - Algorithms
1、排序演算法:快速排序、歸併排序、計數排序
2、搜尋演算法:回溯、遞迴、剪枝技巧
3、圖論:最短路、最小生成樹、網路流建模
4、動態規劃:揹包問題、最長子序列、計數問題
5、基礎技巧:分治、倍增、二分、貪心
資料結構 - Data Structures
1、陣列與連結串列:單/雙向連結串列、跳舞鏈
2、棧與對列
3、樹與圖:最近公共祖先、並查集
4、雜湊表
5、堆:大/小根堆、可並堆
6、字串:字典樹、字尾樹
遞迴與迭代的區別
遞迴(recursion):遞迴常被用來描述以自相似方法重複事物的過程,在數學和電腦科學中,指的是在函式定義中使用函式自身的方法。(A呼叫A)
迭代(iteration):重複反饋過程的活動,每一次迭代的結果會作為下一次迭代的初始值。(A重複呼叫B)
遞迴是一個樹結構,從字面可以其理解為重複“遞推”和“迴歸”的過程,當“遞推”到達底部時就會開始“迴歸”,其過程相當於樹的深度優先遍歷。
迭代是一個環結構,從初始狀態開始,每次迭代都遍歷這個環,並更新狀態,多次迭代直到到達結束狀態。
# 理論上遞迴和迭代時間複雜度方面是一樣的,但實際應用中(函式呼叫和函式呼叫堆疊的開銷)遞迴比迭代效率要低。
連結:https://www.jianshu.com/p/32bcc45efd32
來源:簡書
演算法的時間複雜度和空間複雜度
-
時間複雜度和空間複雜度是用來評價演算法效率高低的2個標準。
-
時間複雜度:就是說執行演算法需要消耗的時間長短,越快越好。比如你在電腦上開啟計算器,如果一個普通的運算要消耗1分鐘時間,那誰還會用它呢,還不如自己口算呢。
-
空間複雜度:就是說執行當前演算法需要消耗的儲存空間大小,也是越少越好。本來計算機的儲存資源就是有限的,如果你的演算法總是需要耗費很大的儲存空間,這樣也會給機器帶來很大的負擔。
時間複雜度的計算
表示方法
我們一般用“大O符號表示法”來表示時間複雜度:T(n) = O(f(n)) n是影響複雜度變化的因子,f(n)是複雜度具體的演算法。
常見的時間複雜度量級
-
常數階O(1)
-
線性階O(n)
-
對數階O(logN)
-
線性對數階O(nlogN)
-
平方階O(n²)
-
立方階O(n³)
-
K次方階O(n^k)
-
指數階(2^n)
常見的時間複雜度(按效率排序) O(1)<O(logn)<O(n)<O(nlogn)<O(n2)<O(n2logn)<O(n3)
接下來再看一下不同的複雜度所對應的演算法型別。
常數階O(1)
int a = 1;
int b = 2;
int c = 3;
線性階O(n)
for(i = 1; i <= n; i++) {
j = i;
j++;
}
對數階O(logN)
int i = 1;
while(i < n) {
i = i * 2;
}
線性對數階O(nlogN)
for(m = 1; m < n; m++) {
i = 1;
while(i < n) {
i = i * 2;
}
}
平方階O(n²)
for(x = 1; i <= n; x++){
for(i = 1; i <= n; i++) {
j = i;
j++;
}
}
空間複雜度計算
空間複雜度 O(1)
如果演算法執行所需要的臨時空間不隨著某個變數n的大小而變化,即此演算法空間複雜度為一個常量,可表示為 O(1)。
int i = 1;
int j = 2;
++i;
j++;
int m = i + j;
程式碼中的 i、j、m 所分配的空間都不隨著處理資料量變化,因此它的空間複雜度 S(n) = O(1)。
空間複雜度 O(n)
int[] m = new int[n]
for(i = 1; i <= n; ++i) {
j = i;
j++;
}
這段程式碼中,第一行new了一個數組出來,這個資料佔用的大小為n,後面雖然有迴圈,但沒有再分配新的空間,因此,這段程式碼的空間複雜度主要看第一行即可,即 S(n) = O(n)。
十大經典排序演算法
# 氣泡排序
比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。
對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最後一對。這步做完後,最後的元素會是最大的數。
針對所有的元素重複以上的步驟,除了最後一個。
持續每次對越來越少的元素重複上面的步驟,直到沒有任何一對數字需要比較。
import sys
sys.setrecursionlimit(1000000)
## 氣泡排序 (******)
### 時間複雜度:O(n^2)
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
return li
## 選擇排序
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
再從剩餘未排序元素中繼續尋找最小(大)元素,然後放到已排序序列的末尾。
重複第二步,直到所有元素均排序完畢。
#### 時間複雜度:O(n^2)
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]
return li
##### 插入排序(打撲克牌)
將第一待排序序列第一個元素看做一個有序序列,把第二個元素到最後一個元素當成是未排序序列。
從頭到尾依次掃描未排序序列,將掃描到的每個元素插入有序序列的適當位置。(如果待插入的元素與有序序列中的某個元素相等,則將待插入元素插入到相等元素的後面。)
#### 時間複雜度: O(n^2)
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
## 快速排序
1、從數列中挑出一個元素,稱為 "基準"(pivot);
2、重新排序數列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的後面(相同的數可以到任一邊)。在這個分割槽退出之後,該基準就處於數列的中間位置。這個稱為分割槽(partition)操作;
3、遞迴地(recursive)把小於基準值元素的子數列和大於基準值元素的子數列排序;
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