算法与分析设计期末重点复习

  1 //@author 软工.林
  2 
  3 算法 完蛋!
  4 填空题把书里第一章,其他算法章节在写代码之前的字看完 20分
  5 计算题三大道(估摸就能知道考什么 除非考重复知识点)30分
  6 完善算法 估计下面出 20分
  7 综合分析不知道 不会啊 估计数学归纳法证明贪心? 30分
  8 
  9 填空题能考的东西:
  算法性质:输入 输出 有限 确定
  时间复杂度大O表示法的使用
  递归式的时间复杂度求解
   衡量算法的好坏:时间复杂度
  (一)
  分治法的基本思想:将规模较大的不容易解决的大问题分割为性质相同但规模较小的子问题,若子问题容易求解,分别求解子问题,由子问题的解构造出原问题的解

  能用分治法问题的特征:易分解为规模小的子问题 规模小到一定程度容易求解 各个子问题相互独立 子问题的解可以合并成原问题的解
  分治法求解问题步骤:分解Divide->递归求解子问题Conquer->Merge合并 反正就是分解求值合并

  递归:在函数定义中调用函数自身的方法,使用自身定义的函数称为递归函数。
  递归:需要有递归边界和递归表达式
  二分搜索应用分治法 将规模为n的问题简化为规模为n/2的问题
  二分搜索 T(n) = O(1) WHEN n = 1, T(n/2) + O(1) WHEN n > 1
  Tn = O(logn)

  合并排序
  排序思想 将n个元素分成两个规模大致相同的子数组 继续分割直到单元素 后将相邻的元素合并 (合并期间就是排序)
  
  快速排序
  通过交换达到排序 最好情况 (划分平衡)将规模为n的问题分解为两个规模为n/2 的子问题 O(nlogn) 最坏情况 有序数组,O(n^2)
  可以知道 快速排序执行效率取决于基准元素的选择
  常常用平衡快速排序法(取数组开头中间结尾三个数的中位数作为基准元素)和基于随机支点选择的快排(最坏情况下依然是O(n^2)) 平均都是 O(nlogn)
  
  线性时间选择:找第K小 借助快排中的分割步骤(以第一个元素为基准,把小于基准的放在左边,大于基准元素的放在右边)
  然后找第K小,找不到再在这个数的两边找就完事了 记住75这个数字

(二)

  动态规划解决的问题:有最优子结构和子问题重叠性质
  最优子结构:问题的最优解包含其子问题的最优解(也就是说由子问题的最优解可以得出问题的最优解)
  子问题重叠性质:问题求解过程中,大量子问题重复出现
  步骤:分析最优解性质并找出其结构特征,建立最优值递归定义,自底向上计算,构造问题最优解
  最长公共子序列:c[i][j]= 0 (i = 0 or j = 0) , c[i - 1][j - 1] + 1(i,j > 0 and xi = yj), max{c[i-1][j],c[i][j-1]},(i,j>0 and xi != yj)
  
  最优二叉搜索树也可以考证明题 p45(书本)
  二叉搜索树:每个结点都不比它的左子节点任意元素小 而且不比它的右子树的任意元素大
  其递归定义为:若左子树不空,左子树上所有结点的值均小于它的根节点的值;
          若右子树不空,右子树上所有的结点的值均大于它的根节点的值;
          左右子树分别为二叉搜索树
  (三)
  贪心算法总是做局部最优选择,即当前问题的最优选择。
  能运用贪心算法的问题有贪心选择性质(所求问题的整体最优解可以通过一系列局部最优选择来达到)
              和最优子结构特征(一个问题的最优解包括其子问题的最优解)
  哈夫曼树算法:O(nlogn)
  
  单源最短路径:没什么好记的,就不短找第一个点到剩下的点的集合的距离的最小值,并在取出剩下的点中的一个后,将剩下的点与第一个点的距离更新,
        直至把除了第一个点的所有的点从剩下的点中取出来。
最小生成树:prim算法 O(n^2) 每次找出来最短的边加入就完事了 p76
  
  (四)
  回溯法:在问题的解空间中以深度优先搜索(dfs)搜索问题的解
  步骤:定义问题的解空间(由所有可能的解构成) ->为了方便搜索,建立合适的解空间结构(子集树 和 排列树 两种中选一种)->dfs解空间树
  当我们求解的结果是集合SS的某一子集的时候,其对应的解空间是子集树。时间复杂度O(2^n)

 


   当我们求解的结果是集合SS的元素的某一种排列的时候,其对应的解空间就是排列树。时间复杂度O(n!) 典型问题为旅行商问题(TSP) 批处理作业调度(O(nn!))

  

 

 


  回溯法通常用约束函数剪去不满足约束条件的子树,限界函数剪去不能得到最优解的子树 这两种函数统称剪枝函数
  回溯法讲了:装载问题 批处理作业调度 n皇后(O(n*n^n)) 最大团问题 图的m着色
  
  最大团问题:p105 太恶心了不想写了
  

  (四)
  分支限界法(就是广度优先搜索。。。)
  P117
  


10 主定理法解递归表达式的时间复杂度 必考 11 Tn = O(1) n = 1 12 aT(n/b) + f(n) n > 1 13 14 解得:Tn = O(n^k) a < b^k 15 = O((n^k) * logb n) a = b^k 16 = O(n^logba) a > b^k 17

  *********下面在上课有讲过计算或者填表的一定要去看当时的笔记!********** 18 0-1背包(估计考填表) 19 最优二叉搜索树 20 21 C为背包容量 22 w(weight) v(value) m[i][j]背包容量为j,可选择物品为i,i + 1, ... n时 0-1背包的最优值 23 //count the best answer 24 public static void knapsack(int[] v, int[] w, int c, int[][] m){ 25 int jMax = Math.min(w[n] - 1, c); 26 for(int j = 0; j <= jMax; j ++){ 27 m[n][j] = 0; 28 } 29 30 for(int j = w[n]; j <= c; j ++){ 31 m[n][j] = v[n]; 32 } 33 //**************key 34 for(int i = n - 1; i > 1; i --){ 35 jMax = Math.min(w[i] - 1, c); 36 for(int j = 0; j <= jMax; j ++){ 37 m[i][j] = m[i + 1][j]; 38 for(int j = w[i]; j <= c; j ++){ 39 m[i][j] = Math.max(m[i + 1][j], m[i + 1][j - w[i]] + v[i]); 40 } 41 } 42 } 43 //**************key 44 m[1][c] = m[2][c]; 45 if(c >= w[1]) m[1][c] = Math.max(m[1][c], m[2][c - w[1]] + v[1]); 46 } 47 48 //get the best answer 49 public static void traceback(int[][] m, int[] w, int c, int[] x){ 50 for(int i = 1;i < n; i ++){ 51 if(m[i][c] == m[i + 1][c]) x[i] = 0; 52 else{ 53 x[i] = 1; 54 c-=w[i]; 55 } 56 x[n] = (m[n][c] > 0)?1:0; 57 } 58 } 59 60 //bst 61 public static void optimalBinarySearchTree(float[] a, float[] b, float[][] m, int[][] s, float[][] w){ 62 for(int i = 0; i <= n; i ++){ 63 w[i + 1][i] = a[i]; 64 m[i + 1][i] = 0; 65 } 66 67 for(int r = 0; r < n; r ++){ 68 for(int i = 1; i <= n - r; i ++){ 69 int j = i + r; 70 w[i][j] = w[i][j - 1] + a[j] + b[j]; //=> 71 w[i][j] = m[i][i - 1] + m[i + 1][j]; //=>min{m[i][k - 1],m[k + 1][j]} 72 s[i][j] = i; //=> 73 for(int k = i + 1; k <= j; k ++){ 74 float t = m[i][k - 1] + m[k + 1][j]; 75 if(t < m[i][j]){ 76 m[i][j] = t; 77 s[i][j] = k; 78 } 79 m[i][j] += w[i][j]; 80 } 81 } 82 83 } 84 } 85 86 87 贪心算法总是做局部最优选择 88 当一个问题既具有贪心选择性质又具有最优子结构性质时,必能用贪心算法得到整体最优解。 89 Dij(可能考计算填表把我觉得 p71) 90 public static Bintree huffmanTree(float[] f){ 91 int n = f.length; 92 Huffman[] w = new Huffman[n + 1]; 93 Bintree zero = new Bintree(); 94 for(int i = 0; i < n; i ++){ 95 Bintree x = new Bintree(); 96 x.makeTree(new MyInteger(i), zero, zero); 97 w[i + 1] = new Huffman(x, f[i]); 98 } 99 MinHeap H = new MinHeap(); 100 H.initialize(w, n); 101 for(int i = 1; i < n; i ++){ 102 Huffman x = (Huffman).H.removemin(); 103 Huffman y = (Huffman).H.removemin(); 104 Bintree z = new Bintree(); 105 z.makeTree(null,x.tree,y.tree); 106 Huffman t = new Huffman(z,x.weight+y.weight); 107 H.put(t); 108 } 109 110 return ((Huffman)H.removemin()).tree; 111 }
  //dist[]从源点到顶点xxx的最短特殊路径长度,prev[]记录从源点到顶点xxx的最短路径的前一个顶点 p71
112 public static void dijkstra(int v,float[][] a, float[] dist, int[] prev){ 113 if(v < 1 || v > n) return; 114 boolean[] s = new boolean[n + 1]; 115 for(int i = 1; i < n; i ++){ 116 dist[i] = a[v][i]; 117 s[i] = false; 118 if(dist[i] = Float.MAX_VALUE) prev[i] = 0; 119 else prev[i] = v; 120 } 121 dist[v] = 0; s[v] = true; 122 for(int i = 1; i < n; i ++){ 123 float temp = Float.MAX_VALUE; 124 int u = v; 125 for(int j = 1; j <= n; j ++){ 126 if(!s[j] && (dist[j] < temp)){ 127 u = j; 128 temp = dist[j]; 129 } 130 s[u] = true; 131 for(int j = 1; j <= n; j ++){ 132 if(!s[j] && (a[u][j] < Float.MAX_VALUE)){ 133 float newdist = dist[u] + a[u][j]; 134 if(newdist < dist[j]){ 135 dist[j] = newdist; 136 prev[j] = u; 137 } 138 } 139 } 140 } 141 } 142 } 143 144 批处理作业调度 145 /* 146 n个作业 J1...Jn 147 注意:时间均为从机器x启动到该作业完成的时间 148 f1,i表示Ji在第一台机器的处理时间 149 f2,i表示Ji在第二台机器的处理时间 150 规定第一个任务必须在第一台机器处理完成之后才能在第二台机器处理 151 152 找问题方案x->为作业的处理顺序 如x = [3,1,2]为作业3->作业2->作业1 153 154 解决方法:搜索 搜索大法好! 155 */ 156 class FlowShop{ 157 //n 作业数 f 时间和 f1 机器1完成时间 f2 机器2完成时间 bestf当前最优值 158 static int n, f1, f, bestf; 159 static int[][] m;//各作业所需的处理时间 160 static int[] x; //当前作业调度方案 161 static int[] bestx; //当前最优作业调度 162 static int[] f2; //机器2完成处理时间 163 public static void backtrack(int i){ 164 if(i > n){ 165 for(int j = 1; j <= n; j ++){ 166 bestx[j] = x[j]; 167 } 168 bestf = f; 169 } 170 else{ 171 for(int j = i; j <= n; j ++){ 172 f1 += m[x[j]][1]; 173 f2[i] = ((f2[i - 1] > f1)? f2[i - 1]: f1) + m[x[j]][2]; 174 f+=f2[i]; 175 176 if(f < bestf){ 177 swap(i, j); 178 backtrack(i + 1); 179 swap(i, j); 180 } 181 f1 -= m[x[j]][1]; 182 f -= f2[i]; 183 } 184 } 185 } 186 } 187 188 图的着色问题 就一个结点一个结点搜索下去就完事了 不行就回溯就这样 189 190 class Coloring{ 191 //图的点数 192 static int n; 193 194 //可用颜色数 195 static int m; 196 197 //图的邻接矩阵 198 static boolean [][]a; 199 200 //当前解 201 static int[] x; 202 203 //当前已找到的m可着色方案数 204 static long num; 205 206 public static long mColoring(int mm){ 207 m = mm; 208 sum = 0; 209 backtrack(1); 210 return sum; 211 } 212 213 private static void backtrack(int t){ 214 if(t > n){ 215 sum ++; 216 for(int i = 1; i <= n; i ++){ 217 System.out.print(x[i] + ' '); 218 System.out.println(); 219 } 220 } 221 else{ 222 for(int i = 1; i <= m; i ++){ 223 x[t] = i; 224 //ok函数保证相邻两点的颜色不一样 225 if(ok(t)) backtrack(t + 1); 226 x[t] = 0; 227 } 228 } 229 } 230 231 private static boolean ok(int k){ 232 for(int j = 1; j <= n; j ++){ 233 //估计考这个条件填空 234 if(a[k][j] && (x[j] == x[k])){ 235 return false; 236 } 237 return true; 238 } 239 } 240 }

 

posted @ 2021-06-27 18:11  WriteOnce_layForever  阅读(481)  评论(0编辑  收藏  举报