美文网首页
数据结构与算法之美-主定理方法(master theorem)和

数据结构与算法之美-主定理方法(master theorem)和

作者: 魏鹏飞 | 来源:发表于2019-10-04 18:44 被阅读0次

    1. Merge Sort - 归并排序

    核心:归并排序是采用分治法的一个非常典型的应用。归并排序的思想就是先递归分解数组,再合并数组。

    将数组分解最小之后,然后合并两个有序数组,基本思路是比较两个数组的最前面的数,谁小就先取谁,取后相应指针就往后移一位。然后再比较,直至一个数组为空,最后把另一个数组的剩余部分复制过来即可。

    归并排序的分析
    1. Python代码实现
    
    """
    归并排序是采用分治法的一个非常典型的应用。归并排序的思想就是先递归分解数组,再合并数组。
    
    最好时间复杂度:O(nlogn)
    最坏时间复杂度:O(nlogn)
    稳定性:稳定
    """
    
    class Sort(object):
    
        def mergeSort(self, alist):
            n = len(alist)
    
            if n <= 1:
                return alist
    
            mid = n // 2
            # 二分分解
            leftList = self.mergeSort(alist[:mid])
            rightList = self.mergeSort(alist[mid:])
    
            # 合并
            return self._merge(leftList, rightList)
    
    
        def _merge(self, leftList, rightList):
            """
            合并操作,将两个有序列表leftList和rightList合并成一个大的有序列表
            """
            l = r = 0
            tempList = []
            while l < len(leftList) and r < len(rightList):
                if leftList[l] <= rightList[r]:
                    tempList.append(leftList[l])
                    l += 1
                else:
                    tempList.append(rightList[r])
                    r += 1
                
            tempList += leftList[l:]
            tempList += rightList[r:]
            return tempList
    
    if __name__ == "__main__":
        alist = [6, 5, 3, 1, 4, 7, 2, 4]
        print(alist)
        mergeSort = Sort()
        sortAlist = mergeSort.mergeSort(alist)
        print(sortAlist)
    
    # 结果
    [6, 5, 3, 1, 4, 7, 2, 4]
    [1, 2, 3, 4, 4, 5, 6, 7]
    

    归并排序复杂度分析,可以写成递推公式:
    T(n)=T(\frac{n}{2}) + T(\frac{n}{2}) + n=2T(\frac{n}{2})+n2T(\frac{n}{2})为分解成两部分排序的时间复杂度,n为合并这两部分已排序数组的时间复杂度。由主定理可求解时间复杂度。

    2. 主定理方法

    定理

    简化记忆:

    • O(n^{log_ba})>f(n) \Longrightarrow O(n^{log_ba})
    • O(n^{log_ba})=f(n)=O(n^{log_ba}log^kn) \Longrightarrow O(n^{log_ba}log^{k+1}n)
    • O(n^{log_ba})<f(n) \Longrightarrow f(n)

    1. 举例一:
      T(n)=3T(n/2)+n^2复杂度。

    n^{log_ba} = n^{log_23} \approx n^{1.6} \\< \\f(n)=n^2

    结果为O(n^2)

    1. 举例二:
      T(n)=4T(n/2)+n^2复杂度。

    n^{log_ba} = n^{log_24} \approx n^2 \\= \\f(n)=n^2 =n^{log_ba}log^kn

    结果为k = 0, O(n^{log_ba}log^{k+1}n)=O(n^2logn)

    1. 举例三:
      T(n)=16T(n/4)+n复杂度。

    n^{log_ba} = n^{log_416} \approx n^2 \\> \\f(n)=n

    结果为O(n^2)

    1. 举例四:
      T(n)=2T(n/4)+n^{0.51}复杂度。

    n^{log_ba} = n^{log_42} \approx n^{0.5} \\< \\f(n)=n^{0.51}

    结果为O(n^{0.51})


    3. 斐波那契数|递归树分析法

    序列一次为 1,1,2,3,5,8,13,21,......
    问题:怎么求出序列中第N个数?

    # 递归形式
    def fib(n):
        if n <= 1:
            return n
        return fib(n-1)+fib(n-2)
    
    print(fib(5))
    
    # 结果
    5
    

    时间复杂度怎么计算?
    T(n)=T(n-1)+T(n-2)此时不能套用主定理。使用递归树分析:时间复杂度为O(2^n)

    递归树分析法

    空间复杂度如何分析?
    递归时f(n)=f(n-1)+f(n-2)有较多的压栈操作。空间复杂度为O(n)

    出入栈

    斐波那契循环实现:

    # 非递归形式
    #!/usr/bin/python
    def fib(n):
        a = 0
        b = 1
        for i in range(n):
            a, b = b, a + b
        return a
    
    print(fib(5))
    
    # 结果
    5
    

    此时的时间复杂度为O(n)

    思考:怎么在O(1)的时间复杂度下计算fib(n)?
    答案:通项公式,a_n=\frac{1}{\sqrt5}[(\frac{1+\sqrt5}{2})^n-(\frac{1-\sqrt5}{2})^n]

    参考文献

    1. Introdution to Algorithem

    相关文章

      网友评论

          本文标题:数据结构与算法之美-主定理方法(master theorem)和

          本文链接:https://www.haomeiwen.com/subject/enuqpctx.html