MIT6.00.1X 計算機科學和PYTHON編程導論 第五週

第九講    效率和增加量級python

    咱們的首要目標就是讓代碼正常運行,可以計算出正確的答案。儘管如此,咱們仍是但願代碼可以達到第二個目標,即高效地進行計算。一般而言,第一個目標更加劇要,但有時候第二個目標也十分重要,同時咱們須要平衡計算的複雜度和理解代碼的複雜度。git

   複雜度 :算法

        咱們假設一個基本步驟就是一個操做,而這個操做的用時老是同樣的,以後咱們只需專一於數清楚計算函數時所執行的基本步驟便可。測量複雜度咱們只關心增幅最快的項,而且忽略係數。app

    例:函數

def f(x):
    for i in range(1000):
        ans = i
    for i in range(x):
        ans += 1
    for i in range(x):
        for j in range(x):
            ans += 1
#這一段代碼的步驟總數爲1000+2x+2x^2,對於其複雜度咱們只關心增加最快的項即2x^2,
#同時咱們不關心繫數就獲得該函數的複雜度x^2。對於複雜度咱們使用大寫的O表示,
#則該函數的複雜度表示爲O(n^2)

       常見的複雜度(耗時,由低到高):code

        O(1)          常數時間算法,運算時間不隨運算量的增長而增長排序

        O(log n)    對數時間算法索引

        O(n)          線性時間算法內存

        O(n * log n)    對數-線性時間算法element

        O(n^c)        多項式時間算法

        O(c^n)        指數時間算法

# 對數時間算法
def intToStr(i):
    digits = '0123456789'
    if i == 0:
        return '0'
    result = ''
    while i > 0:
        result = digits[i%10] + result
    i = i/10
    return result

# 運算步驟 log10(i) 複雜度 O(log(i))
# 線性時間算法
def addDigits(s):
    val = 0
    for c in s:
    val += int(c)
    return val
#總步驟 len(s)  複雜度O(len(s))
def fact(n):
    if n == 1:
        return 1
    else:
        return n*fact(n-1)

#總步驟 n  複雜度O(n)
# 多項式時間算法
def isSubset(L1, L2):
    for e1 in L1:?
        matched = False
        for e2 in L2:
            if e1 == e2:
                matched = True
                break
        if not matched:
            return False
    return True

# 總步驟爲 len(L1)*len(L2)   這裏咱們只考慮最壞的狀況即 len(L1) == len(L2) 
# 因此這個算法的複雜度爲 O(len(L1)^2)

def intersect(L1, L2):
    tmp = []
    for e1 in L1:
        for e2 in L2:
            if e1 == e2:
                tmp.append(e1)
    res = []
    for e in tmp:
        if not(e in res):
            res.append(e)
    return res
# 總步驟爲 len(L1)*len(L2) + len(L1)  咱們只關心增加最快的項, 
# 因此這個算法的複雜度爲O(len(L1)^2)
# 指數時間算法
def genSubsets(L):
    res = []
    if len(L) == 0:
        return [[]] #list of empty list
    smaller = genSubsets(L[:-1])
    # get all subsets without last element
    extra = L[-1:]
    # create a list of just last element
    new = []
    for small in smaller:
        new.append(small+extra)
    # for all smaller solutions, add one with last element
    return smaller+new
    # combine those with last element and those without

# 總步驟爲 2^(n-1)+..+...+2^0, 因此該算法的複雜度爲O(2^n)

第十講    內存和查找

        咱們能夠同過間接索引的辦法來查找須要的數據。

        通常的對於無序列表的查找,時間複雜度爲O(n),而有序列表可經過二分查找將時間複雜度縮短爲O(log(n)),因此咱們能夠經過對列表排序,使其變成有序的,再使用二分查找,只要咱們找到一種排序算法使得 sort(L) + log(len(L)) < len(L) 則運算效率將會更高,並且對於屢次查找,效率的提高就更加明顯了。

# 選擇排序
def selSort(L):
    for i in range(len(L) - 1):
        minIndx = i
        minVal= L[i]
        j = i + 1
        while j < len(L):
            if minVal > L[j]:
                minIndx = j
                minVal= L[j]
            j += 1
        temp = L[i]
        L[i] = L[minIndx]
        L[minIndx] = temp

# 這裏選擇排序的時間複雜度爲 O(len(L)^2),顯然選擇排序的效率並不高,
# 咱們須要更好的排序方法
# 歸併排序
# 將列表分爲兩部分,分別排序,而後將兩個列表合併
def merge(left, right, compare):
    result = []
    i,j = 0, 0
    while i < len(left) and j < len(right):
        if compare(left[i], right[j]):
            result.append(left[i])
            i += 1
        else:
            result.append(right[j])
            j += 1
    while (i < len(left)):
        result.append(left[i])
        i += 1
    while (j < len(right)):
        result.append(right[j])
        j += 1
    return result

import operator
def mergeSort(L, compare = operator.lt):
    if len(L) < 2:
        return L[:]
    else:
        middle = int(len(L)/2)
        left = mergeSort(L[:middle], compare)
        right = mergeSort(L[middle:], compare)
        return merge(left, right, compare)
# merge的複雜度爲 O(len(L))  mergesort 的複雜度爲 O(len(L) * log(len(L)))
# 簡化爲 O(n*log(n))  歸併排序相比於選擇排序效率提升了不少,這樣的效率咱們能夠接受

    hash:

        哈希的思想以下。給定一個鍵,好比,它指向了一個字典的一個元素。一個哈希函數會將這個鍵轉換爲一個整數,而後它用這個整數來檢索列表。哈希函數可讓咱們查找東西,這個查找過程的用時幾乎獨立於字典的規模。

相關文章
相關標籤/搜索