五大常用算法简介

1      分治算法

1.1      基本概念

把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并

1.2      典型问题

1.2.1        二分搜索

二分查找可以解决(预排序数组的查找)问题:只要数组中包含T(即要查找的值),那么通过不断缩小包含T的范围,最终就可以找到它。一开始,范围覆盖整个数组。将数组的中间项与T进行比较,可以排除一半元素,范围缩小一半。就这样反复比较,反复缩小范围,最终就会在数组中找到T,或者确定原以为T所在的范围实际为空。对于包含N个元素的表,整个查找过程大约要经过log(2)N次比较。

1.2.2        大整数乘法

1.2.3        Strassen矩阵乘法

1.2.4        棋盘覆盖

1.2.5        归并排序

归并排序(Merge Sort)完全遵循上述分治法三个步骤:

  1. 分解:将要排序的n个元素的序列分解成两个具有n/2个元素的子序列
  2. 解决:使用归并排序分别递归地排序两个子序列
  3. 合并:合并两个已排序的子序列,产生原问题的解

归并排序的算法思想,看看下面的图解示例就明白了。

 

 

 

1.2.6        快速排序

该方法的基本思想是:

  (1)先从数列中取出一个数作为基准数。

  (2)分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。

  (3)再对左右区间重复第二步,直到各区间只有一个数。

1.2.7        线性时间选择

1.2.8        最接近点对问题

1.2.9        循环赛日程表

1.2.10    汉诺塔

汉诺塔问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。

综合分析可知把n个盘子从1座(相当第一柱子)移到3座(相当第三柱子):

  (1)把1座上(n-1)个盘子借助3座移到2座。

  (2)把1座上第n个盘子移动3座。

  (3)把2座上(n-1)个盘子借助1座移动3座。

2      动态规划算法

2.1      基本概念

动态规划是通过组合子问题的解而解决整个问题的,通过将问题分解为相互不独立(各个子问题包含有公共的子问题,也叫重叠子问题)的子问题,对每个子问题求解一次,将其结果保存到一张辅助表中,避免每次遇到各个子问题时重新计算。

2.2      典型问题

2.2.1        钢条切割

2.2.2        最长非降子序列的长度

  • 问题描述

一个序列有N个数:A[1],A[2],…,A[N],求出最长非降子序列的长度。

  • 解决方法

d(i) = max{1, d(j)+1},其中j<i,A[j]<=A[i]

想要求d(i),就把i前面的各个子序列中, 最后一个数不大于A[i]的序列长度加1,然后取出最大的长度即为d(i)。 当然了,有可能i前面的各个子序列中最后一个数都大于A[i],那么d(i)=1, 即它自身成为一个长度为1的子序列。

2.2.3        最长公共子序列

  • 动态规划解决过程

1)描述一个最长公共子序列

  如果序列比较短,可以采用蛮力法枚举出X的所有子序列,然后检查是否是Y的子序列,并记录所发现的最长子序列。如果序列比较长,这种方法需要指数级时间,不切实际。

  LCS的最优子结构定理:设X={x1,x2,……,xm}和Y={y1,y2,……,yn}为两个序列,并设Z={z1、z2、……,zk}为X和Y的任意一个LCS,则:

      (1)如果xm=yn,那么zk=xm=yn,而且Zk-1是Xm-1和Yn-1的一个LCS。

  (2)如果xm≠yn,那么zk≠xm蕴含Z是是Xm-1和Yn的一个LCS。

  (3)如果xm≠yn,那么zk≠yn蕴含Z是是Xm和Yn-1的一个LCS。

  定理说明两个序列的一个LCS也包含两个序列的前缀的一个LCS,即LCS问题具有最优子结构性质。

2)一个递归解

  根据LCS的子结构可知,要找序列X和Y的LCS,根据xm与yn是否相等进行判断的,如果xm=yn则产生一个子问题,否则产生两个子问题。设C[i,j]为序列Xi和Yj的一个LCS的长度。如果i=0或者j=0,即一个序列的长度为0,则LCS的长度为0。LCS问题的最优子结构的递归式如下所示:

 

 

2.2.4        最优二叉搜索树

 

2.2.5        最长回文字串

 

2.2.6        0-1背包问题

  • 0-1背包问题描述

  有一个窃贼在偷窃一家商店时发现有n件物品,第i件物品价值为vi元,重量为wi,假设vi和wi都为整数。他希望带走的东西越值钱越好,但他的背包中之多只能装下W磅的东西,W为一整数。他应该带走哪几样东西?

0-1背包问题中:每件物品或被带走,或被留下,(需要做出0-1选择)。小偷不能只带走某个物品的一部分或带走两次以上同一个物品。

部分背包问题:小偷可以只带走某个物品的一部分,不必做出0-1选择。

  • 0-1背包问题解决方法

  0-1背包问题是个典型举办子结构的问题,但是只能采用动态规划来解决,而不能采用贪心算法。因为在0-1背包问题中,在选择是否要把一个物品加到背包中,必须把该物品加进去的子问题的解与不取该物品的子问题的解进行比较。这种方式形成的问题导致了许多重叠子问题,满足动态规划的特征。动态规划解决0-1背包问题步骤如下:

0-1背包问题子结构:选择一个给定物品i,则需要比较选择i的形成的子问题的最优解与不选择i的子问题的最优解。分成两个子问题,进行选择比较,选择最优的。

0-1背包问题递归过程:设有n个物品,背包的重量为w,C[i][w]为最优解。即:

 

 

2.2.7        装配线调度问题

  • 动态规划解决步骤

1)描述通过工厂最快线路的结构

  对于装配线调度问题,一个问题的(找出通过装配站Si,j 最快线路)最优解包含了子问题(找出通过S1,j-1或S2,j-1的最快线路)的一个最优解,这就是最优子结构。观察一条通过装配站S1,j的最快线路,会发现它必定是经过装配线1或2上装配站j-1。因此通过装配站的最快线路只能以下二者之一:

a)通过装配线S1,j-1的最快线路,然后直接通过装配站Si,j

b)通过装配站S2,j-1的最快线路,从装配线2移动到装配线1,然后通过装配线S1,j

为了解决这个问题,即寻找通过一条装配线上的装配站j的最快线路,需要解决其子问题,即寻找通过两条装配线上的装配站j-1的最快线路。

2)一个递归的解

  最终目标是确定底盘通过工厂的所有路线的最快时间,设为f*,令fi[j]表示一个底盘从起点到装配站Si,j的最快时间,则f* = min(f1[n]+x1,f2[n]+x2)。逐步向下推导,直到j=1。

当j=1时: f1[1] = e1+a1,1,f2[1] = e2+a2,1

当j>1时:f1[j] = min(f1[j-1]+a1,jf2[j-1]+t2,j-1+a1,j)f2[j] = min(f2[j-1]+a2,jf1[j-1]+t1,j-1+a2,j)

 

 

 

3      回溯法

3.1      基本概念

回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。

回溯法解题步骤:

1) 定义问题解空间;

2) 确定易于搜索的解空间结构;

3) 深度优先搜索树解空间,并且运用剪枝函数避免无效搜索。

3.2      典型问题

3.2.1        八皇后问题

八皇后问题是在8*8的棋盘上放置8枚皇后,使得棋盘中每个纵向、横向、左上至右下斜向、右上至左下斜向均只有一枚皇后。八皇后的一个可行解如图所示:

 

 

 

思路:

对于八皇后的求解可采用回溯算法,从上至下依次在每一行放置皇后,进行搜索,若在某一行的任意一列放置皇后均不能满足要求,则不再向下搜索,而进行回溯,回溯至有其他列可放置皇后的一行,再向下搜索,直到搜索至最后一行,找到可行解(所有),输出。

4      贪心算法

4.1      基本概念

在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。

4.2      典型问题

 

 

5      分支界限法

5.1      基本概念

类似于回溯法,也是一种在问题的解空间树T上搜索问题解的算法。但在一般情况下,分支限界法与回溯法的求解目标不同。回溯法的求解目标是找出T中满足约束条件的所有解,而分支限界法的求解目标则是找出满足约束条件的一个解,或是在满足约束条件的解中找出使

某一目标函数值达到极大或极小的解,即在某种意义下的最优解。

5.2      典型问题

 

posted @ 2019-10-24 14:03  流浪的小丑  阅读(...)  评论(...编辑  收藏