1. 程式人生 > >面試常問的小演算法總結

面試常問的小演算法總結

圖的最短路徑演算法

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。因此稀疏圖選用鄰接表來儲存要比鄰接矩陣來儲存要好很多。

漢諾塔

image.png

楊輝三角

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, 也就是說它只有兩行,要找出最大子矩陣,我們要從左到右不斷的遍歷才能找出在這種情況下的最大子矩陣。如果我們把這兩行上下相加,情況就和求“最大子段和問題” 又是一樣的了。

KMP演算法

LCS/最長公共子序列/最長公共子串