算法导论期末复习

算法


期末复习的时候记的笔记,分享给大家~

第二章 算法基础
为了解决一个给定的问题 算法一次或多次的递归调用其自身以解决紧密相关的若干子问题。遵循分治的思想:将原问题分解为几个规模娇小但类似于原问题的子问题,递归求解子问题,合并子问题的解来建立原问题的解。 

分析算法,要有一个模型,描述所用资源极其代价的模型。我们通常想度量的是计算时的运行时间。
RAM:
随机存取机(RAM)计算模型。
    - 指令一个接一个地执行,没有并行操作。 
    - 每次,程序指令都作为原子操作执行。 一条指令包括算术运算,逻辑运算,数据移动和控制操作。 
    - 每个这样的指令都需要一定的时间。 
    - RAM容量足够大。

忽略高阶项的常系数和低阶项的一个很好的理由是RAM模型不是完全现实的(不是所有的操作都是相同的)。

When we say “the running time is O(n2)” we mean that the worst-case running time is O(n2) – the best case might be better. 


Divide - and - Conquer :
分解,解决,合并。
主定理
Insert Sort Algorithm:具有空间原址性
    插入排序最坏情况运行时间θ(n^2),Best-case linear in  Ω(n), worst-case quadratic in O(n2)  
    >> Best case: Ω(n) – when the input array is already sorted.     
    >> Worst case: O(n2)– when the input array is reverse sorted.     
    >> We can also say that the worst case running time is Ω(n^2) 

    循环不变式:loop-invariants
        1、初始化:循环的第一次迭代之前它为真。【j=2时A[1]是按序排好的,第一次迭代之前循环不变式成立。】
        2、保持:如果循环的某次迭代之前它为真,那么下一次迭代之前它仍为真。【A[1…j]是按序排列的,for循环的下一次迭代之前j将保持循环不变式】
        3、终止:在循环终止时,不变式为我们提供一个有用的性质,有助于证明算法是正确的。【当j=n+1时,循环终止,A[1…n]已按序排列,就是整个数组,所以整个数组已排序,因此算法正确。】



Merge Sort Algorithm :不具有空间原址性
    归并排序事θ(nlgn)以2为底:递归式的T(n)是表示运行时间,n表示规模,它的总代价:由于总共lgn+1层,每层代价为cn,所以总代价为cn*lgn+cn,忽略低阶项和常量C便得出期望E的结果θ(nlgn)。

算法的最坏情况运行时间给出了任意输入的运行时间的一个上界,知道了这个界,就可以确保这个算法不需要更多的时间。
平均情况运行时间往往和最坏情况大致一样差。
第三章 函数的增长
一旦输入规模n足够大,最坏情况运行时间为θ(nlgn)的归并排序战胜θ(n^2)的插入排序。这时使得只有运行时间的增长量级有关时,我们研究算法的渐进效率。
使用渐进记号来描述算法的运行时间,应用于函数,但是除去了某些细节。我们常常做出一种综合性的覆盖所有可能的输入而不仅仅是最坏情况的陈述。刻画任何输入的运行时间的渐进记号。
f(n)  ∈/=  θ/Ο/Ω(g(n))

f(n) = θ(g(n)):
g(n)是f(n)的一个渐进紧确界(asymptotically tight bound)
θ记号限制一个函数在常量因子内。
f(n) = O(g(n)):
O记号为函数给出一个常量银子内的上界。
f(n) = Ω(g(n)):
Ω记号为函数给出一个常量因子内的下界。

存在√正常量n0,c1,c2,当n>=n0
c1g(n)<=  f(n) = θ(g(n))  <=c2g(n)
0<=f(n) = O(g(n))<=cg(n)只有渐进上界
f(n) = Ω(g(n))>=cg(n)<=0提供渐进下界

二次函数f(x)=an^2+bn+c=θ(n^2)
θ(1)常量或常量函数
θ是比Ο更强的概念θ(g(n))∈Ο(g(n))

求解递归式:
    Substitution method 代入法
        1、猜测解的结构
        2、核实数学归纳法
        3、求解常数,证明解是正确的
    Recursion-tree method 递归树方法
         alogb(n)  = nlogb(a)
    Master method 主方法
    下一章
第四章 分治策略

一、用分治策略求解递归式
在递归树中,每个节点表示一个单一子问题的代价,子问题对应某次递归函数调用。将每层的代价求和得到每层代价,然后将所有层的代价求和,得到所有层次的递归调用的总代价。
递归树最适合用来生成好的猜测,然后用代入法来验证猜测是否正确。

二、用主方法求解递归式
菜谱式额求解方法:
T(n) = aT(n/b) + f(n)
f(n)渐进正函数

    将规模为n的问题分解为a个子问题,每个子问题的规模为n/b,a和b都是正整数。f(n)包含了问题分解和子问题合并的代价。

主定理:
    主方法依赖于主定理:
        令a>=1和b>1是常数,f(n)是一个函数,T(n)是定义在非负整数上的递归式。
            T(n) = aT(n/b) + f(n)

    1、若对于某个常数ε>0,有f(n) =Ο(n^((logba)-ε)),则T(n)=θ(n^logba)。【f(n) < n^logba的情况】
    2、若f(n) = θ(n^logba),则T(n) = θ((n^logba)*lgn) = θ(f(n)*lgn)。【f(n)==n^logba的情况】
    3、若对于某个常数ε>0,有f(n) = Ω(n^((logba)+ε)),且对于某个常数c<1和所有的足够大的n有af(n/b)<=cf(n),则T(n) = θ(f(n))。【f(n) > n^logba的情况】

    总结:
    将f(n)于n^logba做比较,较大的决定了递归式的解。
    1中,f(n)渐进小于n^logba,相差一个n^ε。
    3中,f(n)是多项式意义上的大于,要多一个n^ε,而且还要af(n/b) < cf(n)
第六章 堆排序heapsort
    时间复杂度为O(nlgn)  最后的结果是从小到大排序,数组元素的起始下标在【1】

     MAX-HEAPIFY ensures that a heap is max heap. O(log n) 
    Action of BUILD-MAX-HEAP naive analysis leads to O(nlgn) 
    与插入排序相同,不同于归并排序的是:排序同样具有空间原址性。需要额外的空间存储临时数据。
    在堆排序中,堆指的是数据结构而不是垃圾手机存储机制。

    二叉堆是一个数组,被看成是完全二叉树。树上的每个节点对应一个数组元素。从左向右填充。
    父节点为i,左孩子2i,右孩子2i+1,下标从1开始。

    节点的高度是从最下面往上数,最底层高度为0.或者说该节点到叶节点的最长简单路径上边的数目。
    最大堆:堆中的最大元素放在根节点中。

    【堆排序算法中使用最大堆,最小堆用来构造优先队列。】
    先使用Build_MAX_Heap()建立最大堆,然后把根节点依次与最末尾的元素交换,seapsize递减,重新构造最大堆,直到下标为2为止,打印出的就是从大到小的排序结果。

    堆的定义:
        元素之间的关系:  

完全二叉树中的某结点编号为i,则
1) 若有左孩子,则左孩编号为2i
2)若有右孩子,则右孩子结点编号为2i+1
3)若有双亲,则双亲结点编号为[i/2]

    一句话概括堆排序:
        堆排序(Heap Sort) 
            1) 对一组待排序记录的关键字,首先把它们按堆的定义建成小(大) 顶堆 
            2) 然后输出堆顶的最小(大)关键字所代表的记录,再对剩余的关键 字建堆,以便得到次小(大)的关键字
            3) 如此反复进行,直到全部关键字排成有序序列为止。 
第七章 快速排序 Quick Sort
        不稳定的排序,会打乱相同元素的次序

        Worst-case running time: Θ(n2)     
        Expected running time: Θ(nlgn)     
        Constant hidden in Θ(nlgn) are small

        快速排序和归并排序很像,可以对比记忆,都是使用分治法。
        1、先把数组通过一个枢轴(pivot )x分解成两个子数组,左边的所有元素都小于等于x,右边的子数组元素都大于x。
        2、递归排序子数组。
        3、合并(快速排序并不需要合并,因为每一次分解的结果都是确定一个元素的下标位置)

        快速排序的最坏情况:    运行时间 Θ(n2) 
            1、输入有序。
            2、基于最小元素或者最大元素进行划分。
            3、划分之后一边没有元素。
         What if the split is always 1/10 : 9/10?    
                T(n) ≤ T(9n/10) + T(n/10) + Θ (n)    
         What is the solution to this recurrence? 
            ans:    O(nlgn)

        最好情况:
            每次划分能平衡两边子数组的数量 O(nlgn)

        • Theorem. Any comparison sorting algorithm requires Ω(n lgn) comparisons in the worst case

        快速排序 的速度比归并排序高很多,大约两倍。
        Quicksort in practice:
            A. Quicksort is a great general-purpose sorting algorithm.  
            B. Quicksort is typically over twice as fast as merge sort.  
            C. Quicksort can benefit substantially from code tuning.  
            D. Quicksort behaves well even with caching and virtual memory. 
第八章 线性时间排序
    counting Sort(计数排序)
            A. For x in A, if there are 17 elements less than x in A, then x belongs in output position 18.
            B. How if several elements in A have the same value?
                a) Put the 1st in position 18,  2nd in position 19, 3rd in position 20,…这以过程就是C[A[i]]递增的过程。
            a. How if there are 17 elements not greater than x in A?[<=x]
                a) Put the last one in position 17, the penultimate one in position 16,…这就是最后的那个循环,每次将C[A[i]]递减。

        counting sort assumes that the input consists of integers in a small range,假定A数组分布在连续的小块区域的整数
        稳定排序。相等元素的位置排序前后不变。时间复杂度O(K+n)

    Radix Sort(基数排序)
            a. Good idea: Sort on least-significant digit first with auxiliary stable sort
            b. 正确思想: 首先按照最低位排序,并且需使用稳定的辅助排序算法,也就是说每次最低位排序的时候都是如果最低位相同的话,原址排序。
            c. 时间复杂度O(d(k+n))

    Bucket Sort(桶排序)
        桶排序假定输入是由 随机过程 生成的, 该进程均匀分布元素。
        Bucket sort
            -- ① Allocate a bucket for each value of the key 
                >> That is, insert A[i] into list B[ n A[i]  ]
            -- ② For each bucket 
                >> sort list B[ i ]  with insertion sort
            -- ③ concatenate(连接) the list B[0], B[1],…,B[n - 1] together in order


        Total time to examine all buckets in line 5 is O(n), without the sorting time.


    排序算法总结:
        Sorting methods Worst Case  Best Case   Average Case    Application
        Insert Sort n2  n   n2  Very fast when n<50
        Bubble Sort n2  n   n2  Very fast when n<50
        Merge Sort  n lgn   n lgn   n lgn   Need extra space; good for external sort
        Heap Sort   n lgn   n lgn   n lgn   Good for real-time app.
        Quick Sort  n2  n lgn   n lgn   Practical and fast,large number of data
        Counting Sort   k+n k+n k+n Small, fixed range固定范围; Need extra space
        Radix Sort  d(k+n)  d(k+n)  d(k+n)  Fixed range; Need extra space
        Bucket Sort n   n   n   Uniform distribution均匀分布
第十五章 动态规划 Dynamic Programming
    DP paradigm【范例,典范】
    Assemble-Line Scheduling装配线,流水线调度
        i. 时间复杂度时θ(n)
            a. 最有子结构
                f1[j] = min(f1[j-1] + a1,j, f2[j-1] + t2[j-1] + a1,j)     j>=2
                    = e1 + a1,1                                                           j=1
                f2[j] = min(f2[j-1] + a2,j, f1[j-1] + t1[j-1] + a2,j)     j>=2
                    = e2 + a2,1          
                                                                     j=1
    Matrix-Chain Multiplication 矩阵链乘的次数s

        a. 时间复杂度O(n^3)

        维护一个二维数组m[i][j]
        [p*q] X [q*r]     相乘次数为pqr
        最优子结构:如果最优的加括号方式将其分解为 A i..k 与A k+1..j 的乘积,
        则分别对 A i..k 与 A k+1..j 加括号的方式也一 定是最优的。    
         -- 可以利用 剪切-粘贴 的方式证明最优子结构性质。 
        ( 唯一需要确定的就是 k 的值) 
        最优子结构:
            递归公式:
                m[i,j]        = 0                               i=j
                          =min﹛m[I,k] + m[k+1,j] + pi-1*pk*pj﹜ i< j
        m[i,j]: Ai到Aj之间最少的相乘次数
        p1代表的是A1的列数,A2的行数
        p0代表的是A1的行数…
        A代表矩阵,Ai : [pi-1] * [pi]
optimization Problems:最优化问题
    相比于自上而下,自底向上比较好。
    步骤:
    1、刻画/描述最优解的结构特征;
    2、递归地定义最优解的值。
    3、以自下而上的方式计算方案的值。 
    4、使用已经计算的信息构 造一个 最优解。

        a. Shortest path has optimal substructure
        b. Longest path does not have optimal substructure

    重叠子问题:
        存储在子问题中求解过的选择。
        § Bottom-up dynamic programming algorithm 
        – More efficient 
            » regular pattern of table access can be exploited to reduce time or space 
            » take advantage of the overlapping-subproblems property. 
        § Top-down recursive algorithm
            » repeatedly resolve each subproblem each time it appears in the recursion tree. 
            » recursion overhead 
            » Only work when the total number of subproblems in the recursion is small. 

        来记忆自然但效率低下的递归算法。 
        - 记忆递归算法在表格中维护每个子问题的解决方案。
        - 最初包含一个特殊值,用于指示条目尚未填充。
            当在执行递归算法期间首次遇到子问题时,计算其解决方案,然后将其存储在表中。

Longest Common Subsequence 最长公共子序列
        时间复杂度 O(mn) ,打印结果的时间复杂度O(m+n)
        维护一个二维数组c[i][j]



        剪切粘贴法???       ——     If z=LCS(x,y), then any prefix of z is an LCS of a prefix of x and a prefix of y . 

        会有重叠子问题,故要记录子问题的解。 solving subproblems already solved 
        The number of distinct LCS subproblems for two strings m and n is only mn . 


Max Sum 连续数字最大和

        维护一维数组t[j]
        t[j] = max(t[j-1]+A[j],A[j] ), 1<=j<n
        或者
        t[j]    = t[j-1] + A[i];       t[j-1] > 0
                 = A[i];                    t[j-1] <= 0 
第十六章 贪心法 Greedy Algorithms
    对于许多优化问题,动态规划是过度的。 
    贪婪的算法总是让每一步都看起来最好。 也就是说,它使局部最优解决方案,
    希望这种选择将导致整体的最佳解决方案。不从整体上考虑最优解,只是局部最优解,不是对所有问题都能得到整体最优解,但能产生近似最优解。
    Greedy strategy progresses in a “top-down” 

1、Activity-selection problem  活动选择

        Sij = { ak ∈ S : fi ≤ sk < fk ≤ sj } ⊆ S
        Objective: to create a set of maximum activities Ai that are compatible. 

           We apply cut-and-paste argument to prove the optimal substructure property. 
           可以使用动态规划也可以使用贪心法

        We apply cut-and-paste argument to prove the optimal substructure property.



          什么时候用贪心法?
                 1、Greedy-  choice  property 
                    a global optimal solution can be arrived at by making local optimal (greedy) choice 
                        (instead of bottom up in dynamic programming),
                         iteratively reducing each given problem to a smaller one
                     2、Optimal substructure (the same with that of dynamic programming) 
                     if an optimal solution to the problem contains within it optimal solutions to subproblems 

                    Be able to demonstrate that if optimal solution A with s1, then the set A’ = A - {s1} is an optimal solution to a smaller problem w/o s1. 

2、Fractional Knapsack 分数背包


         0-1 knapsack 0/1背包问题 problem can be solved in time O(n⋅w) using dynamic-programming. 
                前i件物品,书包容量为w时能放的最大价值。
                c[i,w] = max(c[i –1, w], c[i –1, w– wi] + vi)       i>0且w>wi
                        = c[i-1,w]                                                                  wi>w
                        = 0                                                                               w或i=0
                The boundary conditions are     
                    c[0, j] = 0 if j ≥ 0, and c[i, j] = −∞ when j < 0. 

3、Huffman coding 哈夫曼编码
            The idea is that we will use a variable length code instead of a fixed length code
             (3 bits for each character), with fewer bits to store the common characters, 
            and more bits to store the rare characters. 

            左小右大,依次选择最小的两个数生成父节点



    单源点最短路径:
                Dijkstra’s algorithm: O(E+VlgV)
                Bellman-Ford: O(VE)
                Floy-Warshall algorithm
                    cij(k)=mink{cij(k-1),cik(k-1)+ckj(k-1)}
第二十四章 最短路径
              单源点最短路径     
                -- 无负边          >>Dijkstra 算法: O(E+VlgV)     
                -- 一般情况      >>Bellman-Ford: O(VE) 
              每对结点间最短路径     
                    -- 无负边       >> 执行 |V| 次 Dijkstra 算法: O(VE+V2lgV)
                    -- 一般情况  Run Bellman-Ford once for each vertex  
                               d(m)ij = mink{d(m-1)ik+akj }   
                               floyd-washall Algorithm  
                              Johnson Algorithm
回溯法
        回溯法又称试探法。回溯法的基本做法是深度优先搜索,是一种组织 得井井有条的、能避免不必要重复搜索的穷举式搜索算法。即从一条 路往前走,能进则进,不能进则退回来,换一条路再试。 
        这种以深度优先DFS的方式系统地搜索问题的解的算法称为回溯法,它适 用于解一些组合数较大的问题

         对于用回溯法求解的问题,首先要将问题进行适当的转化,得出状态空间树。
        这棵树的每条完整路径都代表了一种解的可能。通过深度优先搜索这棵树,枚举每种可能的解的情况;从而得出结果


        回溯算法使用剪枝函数,剪去一些不可能到达最终状态(即答案状态)的节点,从而减少状态空间树节点的生成。搜索过程中用剪枝函 数避免无效搜索。


1、八皇后问题8-Queens

            利用回溯法解题的具体步骤: 
            (1)描述解的形式,定义一个解空间,它包含问题的所有解。 
            (2)构造状态空间树。 
            (3)构造约束函数(用于杀死节点)。 

        扩展节点、活结点、死结点
            扩展节点:就是当前正在求出它的子节点的节点,在深度优先搜索中, 只允许有一个扩展节点。 •
            活结点:就是通过与约束函数的对照,节点本身和其父节点均满足约束 函数要求的节点; • 
            死结点:反之。由此很容易知道死结点是不必求出其子节点的(没有意 义)。 
第三十四章 NP(non-deterministic Polynomial)多项式复杂度非确定性问题
    【set of decision problems solvable in polynomial time on a NONDETERMINISTIC Turing machine】
    SAT is the first NP-Complete problem,satisfiability Problem布尔逻辑可满足性问题
    Other NP-Complete problems: 
        3-color:Is there a way to assign inputs to a given Boolean (combinational) circuit that makes it true? 
        TSP(旅行商问题): A traveling salesperson needs to visit N cities. Is there a route of length at most D?
        MIS, …

    P  <<  NP  <<  EXP 

P:
Set of all decision problems solvable in polynomial time on a deterministic Turing machine.

猜你喜欢

转载自blog.csdn.net/qq_38232598/article/details/80606878