旧时的一些学习笔记4

3 阅读9分钟
  1. 计算机算法五大特征:①输入,0个或多个;②输出,至少一个;③有限性,有穷性,有限时间内;④确定性,确切无歧义指令;⑤可行性,有效性。

  2. 分支限界法解最大团问题时,活结点表的组织形式是“最大堆”;解单源最短路径问题,是“最小堆”,解旅行售货员问题,是“最小堆”。

  3. Huffman编码算法通过构建哈夫曼树实现,使用优先队列(最小堆)来合并节点,每次操作需要O(logn)时间,总共n个节点,因此总时间复杂度为O(nlogn)。

  4. 分治法(分治策略、最优子结构性质):(子问题独立不重复且方法相同)

    快速排序(O(nlogn));实现循环赛日程表;二分搜索;归并排序;棋盘覆盖问题;选择问题;Strassen矩阵乘法;大整数乘法

  5. 回溯法:构建状态空间树(子集树O(2n),排列树O(n!)),以深度优先(“栈”后进先出LIFO)方式搜索解空间树,逐步探索并回溯,通过约束函数或界限函数剪枝无效分支。最大团问题;排列问题;n皇后问题;0/1背包问题(O(n2ⁿ));旅行售货员问题;图的m着色问题

  6. 动态规划法(重叠子问题、最优子结构性质、无后效性):分治思想,递归求解问题,通过表储存解,自底向上or备忘录法求解。定义、构造、算出最优解。矩阵连乘问题;最长公共子序列算法;0/1背包问题;最大子段和问题(O(n));

  7. 分支限界法:队列式(先进先出FIFO)。构建状态空间树,广度优先or最佳优先搜索&最小耗费优先&最大效益优先,找到最优解,通过约束函数或界限函数剪枝无效分支。最大团问题;单源最短路径问题;0/1背包问题;旅行售货员问题

  8. 贪心法(贪心选择性质、最优子结构性质):最优结构性质,自顶向下求解。哈夫曼编码问题(O(nlogn));单源最短路径问题(Dijkstra算法);最小生成树问题(Prim或Kruskal算法O(eloge))O(n²);(部分)背包问题(n(nlogn))。

  9. 分治法与动态规划法: 同:将待求解的问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。 异:适合于用动态规划法求解的问题,经分解得到的子问题往往不是互相独立的。而用分治法求解的问题,经分解得到的子问题往往是互相独立的。

  10. 动态规划基本步骤:(划分阶段——选择状态——确定决策并写出状态转移方程)

    ①分析最优解的性质,并刻画其结构特征。②递归地定义最优值。③以自底向上的方式或自顶向下的记忆化方法(备忘录法)计算出最优值。④根据计算最优值时得到的型芯,构造一个最优解。

    基本思想:空间换时间

    使用条件:满足最优子结构,满足无后效性,有重叠的子问题。

  11. 分支限界法与回溯法

    同:都是一种在问题的解空间树T中搜索问题解的算法。 异:(1)求解目标不同; (2)搜索方式不同; (3)对扩展结点的扩展方式不同; (4)存储空间的要求不同。

  12. 程序是 ( 算法 ) 用某种程序设计语言的具体实现。

  13. 算法的“确定性”指的是组成算法的每条(指令)是清晰的,无歧义的。

  14. 矩阵连乘问题的算法可由(动态规划)设计实现。

  15. (贪心选择性质)是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。

  16. 快速排序算法是基于(分治策略) 的一种排序算法。

  17. 主定理法仅适用于分治策略导出的递归方程,且需严格满足形式 (T(n) = aT(n/b) + cn的k),其中:

    • 常数 (a ≥ 1)(子问题个数非负);

    • 常数 (b > 1)(子问题规模严格缩小);

    • (f(n)) 是渐进正函数(当 n 足够大时,(f(n) > 0),保证非递归部分有实际耗时)。

      时间复杂度:a>b的k –> O(n的logba);

      = –> O(n的klogbn);

      < –> O(n的k)

    • 渐进符号概念回顾: f(n) = O(g(n)):f(n)的增长率 ≤ g(n)的增长率(上界) f(n) = Ω(g(n)):f(n)的增长率 ≥ g(n)的增长率(下界) f(n) = θ(g(n)):f(n)的增长率 = g(n)的增长率(紧确界)

  18. 拉斯维加斯算法可能找不到解,但一旦找到,解一定是正确的;而蒙特卡罗算法总能找到解,但解可能不正确。

  19. 剪枝函数(约束函数和限界函数)用于提前终止不可能产生解的搜索分支。回溯法的核心策略之一是 “剪枝”—— 在搜索解空间树时,通过剪枝函数判断当前分支是否可能导出有效解。

  20. 左剪枝:当前容量>C(最大容量); 右剪枝:回溯rp(剩余物品总价值)+cp(当前价值) < bestv(当前最优价值)

  21. 确定性算法:分治法、动态规划法贪心法、分支限界法。

  22. 随机算法:数值概率算法、蒙特卡罗、拉斯维加斯、舍伍德等算法。

  23. 算法是指解决问题的(一种方法或一个过程)。

  24. 从分治法的一般设计模式可以看出,用它设计出的程序一般是(递归算法)。

  25. 问题的( 最优子结构性质)是该问题可用动态规划算法或贪心算法求解的关键特征。

  26. 数值概率算法常用于(数值问题)的求解。

  27. 计算一个算法时间复杂度通常可以计算)循环次数、基本操作的频率或计算步)。

  28. 利用概率的性质计算近似值的随机算法是(数值概率算法),运行时以一定的概率得到正确解的随机算法是(蒙特卡罗算法)。

  29. 解决 0/1 背包问题可以使用动态规划、回溯法和分支限界法,其中不需要排序的是(动态规划法),需要排序的是(回溯法,分支限界法)。

  30. 使用回溯法进行状态空间树裁剪分支时一般有两个标准:约束条件和目标函数的界,N 皇后问题和 0/1 背包问题正好是两种不同的类型,其中同时使用约束条件和目标函数的界进行裁剪的是(0/1背包问题),只使用约束条件进行裁剪的是(n皇后问题)。

  31. 回溯法是一种既带有(系统性)又带有(跳跃性)的搜索算法。

  32. 分支限界法是一种既带有(系统性)又带有(跳跃性)的搜索算法。

  33. 回溯法搜索解空间树时,常用的两种剪枝函数为(约束函数)和(界限函数)。

  34. 快速排序算法的性能取决于(划分的对称性)。

  35. Prim 算法利用(贪心)策略求解(最小生成树)问题,其时间复杂度是O(n²)。

  36. 图的 m 着色问题可用(回溯)法求解,其解空间树中叶子结点个数是(mⁿ),解空间树中每个内结点的孩子数是(m)。

  37. 递归:自顶向下,栈

  38. P类问题包含在NP类问题中。

  39. 用动态规划策略求解最长公共子序列问题: (1)给出计算最优值的递归方程。 (2)给定两个序列X={B,C,D,A},Y={A,B,C,B},请采用动态规划策略求出其最长公共子序列,要求给出过程。 答: (1)

image-20251205160550260

  1. 动态规划求解0/1背包问题:

    V(0, j) = 0(0个物品),V(i, 0) = 0(承重量0) V(i, j) = V(i-1, j) 第 i 个物品不能装入, j < wi (超重) V(i, j) = max { vi + V(i-1,j-wj) , V(i-1, j) } j > wi (不超重) i在最优子集中,j-wj:失去空间 i不在最优子集中

  2. 1.背包问题的贪心算法

    void Knapsack (int n, float M, float v [], float w [], float x [])
    {
           Sort (n, v, w);
           int i;
           for (i=1; i<=n; i++) x[i]=0;
           float c=M;
           for (i=1; i<=n; i++) {
              if (w[i]>c) break;
              x[i]=1;
              c - =w[i];###  // 更新剩余容量:剩余容量减去当前物品重量
    }
    	//若还有物品未处理,取剩余容量占该物品重量的比例
       if (i<=n) x[i]=c/w[i]; ###	 // 取最后一个物品的部分  
    }
    

    2.最大子段和: 动态规划算法

    int MaxSum (int n, int a [])
    {
        int sum=0, b=0//sum存储当前最大的b[j], b存储b[j]
        for(int j=1; j<=n; j++)  {  
            if (b>0)  b+= a[j] ;
            else  b=a[j]; ###        //一旦某个区段和为负,则从下一个位置累和
     if(b>sum) sum=b;### //更新全局最大和 }
     return sum;
     }
    

    3.快速排序

    template<class Type>
    void QuickSort (Type a [], int p, int r)
    {
          if (p<r) {
            int q=Partition (a, p, r);###
            QuickSort (a,p,q-1); //对左半段排序  ###  
            QuickSort (a,q+1,r); //对右半段排序  ###
            }
    }
    
    

    4.排列问题

    Template <class Type>
    void perm (Type list [], int k, int m)
    { //产生[list[k:m]的所有排列
        if(k==m)###
         {  //只剩下一个元素
             for (int i=0; i<=m; i++) cout<<list[i];
             cout<<endl;
        }
        else  //还有多个元素待排列,递归产生排列
           for (int i=k; i<=m; i++)###
            {
               swap(list[k],list[i]);
               perm (list, k+1; m);###
               swap(list[k], list[i]);         
         }
      } 
    

    5.给定已按升序排好序的n个元素a[0:n-1],现要在这n个元素中找出一特定元素x。 据此容易设计出二分搜索算法:

    template<class Type> 
    int BinarySearch (Type a [], const Type& x, int l, int r)
    {
         while (l<=r) { ###
            int m = ((l+r)/2);###
            if (x == a[m]) return m;
            if (x < a[m]###) r = m-1; else l = m+1;
            }
        return -1;
    } 
    
    6、合并排序描述如下:
    template<class Type>
    void Mergesort (Type a [], int left, int right)
    {
    if (left<right) {###
    int i=(left+right)/2;###
    Mergesort (a, left, i);
    Mergesort (a, i+1, right);###
    Merge(a,b, left,i,right);//合并到数组b
    Copy(a,b, left,right ); //复制到数组a
    }
    }
    

    7、以下是计算x的m的值的过程

    int power (x, m)
    {//计算xm的值并返回。
    y= (1); i=m;
    While #(i-- >0)
       y=y*x;
     #(Return y);
    }