一切过往,皆为序章,一切未知,皆为终章。

时间复杂度和搜索算法

 

计算时间复杂度

1.一般情况下,我们需要考虑三种常见的情形
    1>最佳情况运行时间是输入最有利的情况下算法的运行时间;
    2>最差情形运行时间是给定输入规模的情况下最长的运行时间;
    3>平均情形运行时间是在给定输入规模的情况下的平均运行时间。

渐进表示法

1.渐进表示法讨论算法运行时间与输入规模之间的关系;作为一种对“特别大”的表示方法,渐进表示法,渐进表示法描述了输入规模趋于无穷大时的算法复杂度;
2.渐进复杂度的规则描述:
    1>如果运行时间是一个多项式的和,那么保留增长速度最快的项,去掉其他各项;
    2>如果剩下的项是个乘积,那么去掉所有的常数。
3.渐进表示法也称为“大O”表示法,大O表示法可以给出一个函数渐进增长的上界。

重要时间复杂度

1.O(1)表示常数运行时间
    与输入规模没有无关
2.O(logn)表示对数运行时间
    增长速度至少是某个输入的对数(二分查找法)
3.O(n)表示线性运行时间
    很多处理列表或其他类型序列的程序具有线性复杂度,因为他们对序列中的每个元素都进行常数(大于0)次处理
4.O(nlogn)表示对数线性运行时间
    它是两个项的乘积,每个项都依赖于输入的规模(归并排序)
5.O(n**K)表示多项式运行时间,K是常数
    最长见的是平方复杂度,也就是说算法复杂度按照输入规模的平方增长
6.O(c**n)表示指数运行时间,这时常数c为底数,复杂度为c的n次方。
    所需的时间要随规模的指数而增长

搜索算法

1.搜索算法就是在一个项目集合中找出一个或一组具有某种特点的项目;我们将项目集合称为搜索空间
2.间接引用:要访问目标元素时,先访问另一个元素,再通过包含在这个元素中的引用来访问目标元素。我们每次使用变量引用于变量绑定的对象时,即是这么做的,而当我们使用一个变量访问列表并使用保存在列表中的引用访问另一个对象时,实际上进行了双重间接引用。
3.二分查找
    **思路**:
        1>选择一个可以将列表L大致一分为二的索引i;
        2>检查是否有L[i] = e;
        3>如果不是,检查L[i]大于还是小于e;
        4>根据上一步的结果,确定在L的左半部分还是右半部分搜索e。
    **代码:**
        def search(L, e):
            """假设L是列表,其中元素按升序排列。
            ascending order.
            如果e是L中的元素,则返回True,否则返回False"""

        def bSearch(L, e, low, high):
            #Decrements high – low
            if high == low:
                return L[low] == e
                mid = (low + high)//2
            if L[mid] == e:
                return True
            elif L[mid] > e:
                if low == mid: #nothing left to search
                    return False
                else:
                    return bSearch(L, e, low, mid - 1)
            else:
                return bSearch(L, e, mid + 1, high)
        if len(L) == 0:
            return False
        else:
            return bSearch(L, e, 0, len(L) - 1)

排序算法

1.选择排序:维持一个循环不变式,他将列表分为前缀部分(L[0:i])和后缀部分(L[i+1:len(L)]),前缀部分已经排好序,而且每个元素都不大于后缀部分中的最小元素。
    **思路:**
        1>基础情形:第一次迭代开始时,前缀集合是空的,也就是说,后缀集合是整个列表,因此,不变式成立
        2>归纳步骤:在算法中的每一步,我们都从后缀集合向前缀集合移动一个元素,移动的方式是将后缀集合中的最小元素添加到前缀集合的末尾
        3>结束:退出循环时,前缀集合包括了整个列表,后缀集合是空的,因此,整个列表按照升序排序。
    **代码:**
        def selSort(L):
            """假设L是列表,其中的元素可以用>进行比较。
                    compared using >.
                对L进行升序排列"""
            suffixStart = 0
            while suffixStart != len(L):
            #检查后缀集合中的每个元素
            for i in range(suffixStart, len(L)):
                if L[i] < L[suffixStart]:
                #交换元素位置
                L[suffixStart], L[i] = L[i], L[suffixStart]
            suffixStart += 1
2.归并排序:是一种典型的分治算法,分治算法就是先找出初始问题的一些简单实例的解,再将这些解组合起来作为初始问题的解
    **思路:**
        1>如果列表的长度是0或1,那么它已经排好序了;
        2>如果列表包含多于1个元素,就将其分为两个列表,并分别使用归并排序法进行排序;
        3>合并结果。
    **代码**
        def merge(left, right, compare):
            """假设left和right是两个有序列表,compare定义了一种元素排序规则。
                返回一个新的有序列表(按照compare定义的顺序),其中包含与
                (left+right)相同的元素。"""

        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

            def mergeSort(L, compare = lambda x, y: x < y):
                """假设L是列表,compare定义了L中元素的排序规则
                    on elements of L
                    返回一个新的具有L中相同元素的有序列表。"""
            if len(L) < 2:
                return L[:]
            else:
                middle = len(L)//2
                left = mergeSort(L[:middle], compare)
                right = mergeSort(L[middle:], compare)
                return merge(left, right, compare)
posted @ 2018-08-18 09:33  爱吃帮帮糖  阅读(1575)  评论(0编辑  收藏  举报