面試常問的小演算法總結
圖的最短路徑演算法
Floyd最短路演算法
核心程式碼:
for(k=1;k<=n;k++)
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(e[i][j]>e[i][k]+e[k][j])
e[i][j]=e[i][k]+e[k][j];
Dijkstra最短路演算法
//Dijkstra演算法核心語句
for(i=1;i<=n-1;i++)
{
//找到離1號頂點最近的頂點
min =inf;
for(j=1;j<=n;j++)
{
if(book[j]==0 && dis[j]<min)
{
min=dis[j];
u=j;
}
}
book[u]=1;
for(v=1;v<=n;v++)
{
if(e[u][v]<inf)
{
if (dis[v]>dis[u]+e[u][v])
dis[v]=dis[u]+e[u][v];
}
}
}
M:邊的數量
N:節點數量
通過上面的程式碼我們可以看出,這個演算法的時間複雜度是O(N2)。其中每次找到離1號頂點最近的頂點的時間複雜度是O(N),這裡我們可以用“堆”(以後再說)來優化,使得這一部分的時間複雜度降低到O(logN)。另外對於邊數M少於N2的稀疏圖來說(我們把M遠小於N2的圖稱為稀疏圖,而M相對較大的圖稱為稠密圖),我們可以用鄰接表(這是個神馬東西?不要著急,下週再仔細講解)來代替鄰接矩陣,使得整個時間複雜度優化到O( (M+N)logN )。請注意!在最壞的情況下M就是N2,這樣的話MlogN要比N2還要大。但是大多數情況下並不會有那麼多邊,因此(M+N)logN要比N2小很多。
用鄰接表代替鄰接矩陣儲存
可以發現使用鄰接表來儲存圖的時間空間複雜度是O(M),遍歷每一條邊的時間複雜度是也是O(M)。如果一個圖是稀疏圖的話,M要遠小於N2。因此稀疏圖選用鄰接表來儲存要比鄰接矩陣來儲存要好很多。
漢諾塔
楊輝三角
def triangles():
N=[1]
while True:
yield N
N.append(0)
N=[N[i-1] + N[i] for i in range(len(N))]
n=0
for t in triangles():
print(t)
n=n+1
if n == 10:
break
迴文數/迴文串
return a == a[::-1]
# 字串/數字
a = len(s)
i = 0
while i <= (a/2):
if s[i] == s[a-1-i]:
i += 1
else:
return False
return True
# 數字
def isPalindrome(x):
if x < 0:
return False
temp = x
y = 0
while temp:
print temp, y*10, temp%10
y = y*10 + temp%10
temp /= 10
return x == y
斐波拉契數列(Fibonacci)
def fibonacci(): # 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89
f = [0] * MAXSIZE
f[0] = 1
f[1] = 1
for i in range(2, MAXSIZE):
f[i] = f[i-1] + f[i-2]
return f
fibs = [1,1]
for i in range(8):
fibs.append(fibs[-2] + fibs[-1])
最大子序列與最大子矩陣問題
陣列的最大子序列問題
給定一個數組,其中元素有正,也有負,找出其中一個連續子序列,使和最大。
最大子矩陣問題
給定一個矩陣(二維陣列),其中資料有大有小,請找一個子矩陣,使得子矩陣的和最大,並輸出這個和。
原始矩陣可以是二維的。假設原始矩陣是一個3 * n 的矩陣,那麼它的子矩陣可以是 1 * k, 2 * k, 3 * k,(1 <= k <= n)。 如果是1*K,這裡有3種情況:子矩陣在第一行,子矩陣在第二行,子矩陣在第三行。如果是 2 * k,這裡有兩種情況,子矩陣在第一、二行,子矩陣在第二、三行。如果是3 * k,只有一種情況。
為了能夠找出最大的子矩陣,我們需要考慮所有的情況。假設這個子矩陣是 2 * k, 也就是說它只有兩行,要找出最大子矩陣,我們要從左到右不斷的遍歷才能找出在這種情況下的最大子矩陣。如果我們把這兩行上下相加,情況就和求“最大子段和問題” 又是一樣的了。