确定性算法
之前我们学过的所有算法其实都有一个共同的特点【难(bushi)】,就是对于确定的输入,算法的核心计算过程以及输出和运行时间是不会变的。但是这就引发了一个问题,举个例子,如果对于一个本身就趋向递增的序列使用快速排序,就会触及算法的时间复杂度底线,甚至在海量的数据量时会直接崩溃,这样我们使用确定性算法去解决这种瞬息万变的问题就十分困难。
非确定性算法
那有的小伙伴自然就会想到,如果面对这样的序列,我直接使用一个带有标记的冒泡排序或者选择排序就可以很快的执行完毕了,确实不错。所以按照这个思路,我们对于任何一组输入,根据他的数据分布特征,选取我们现有的最优的算法去解决,这其实就是随机算法大致的思路。
定义
对于给定的输入,算法的输出或运行时间是不确定的
分类
(1)启发式算法
利用输入数据的特征和信息对于问题进行求解,尽可能地逼近最优解,但是无法知晓和最优解之间的差距
(2)近似算法
对问题给出一个与数据无关的近似最优解,以及对最优解或者最优解上下界的近似比
(3)随机算法
随机数使算法本身成为随机变量,具有概率分布,与数据无关
接下来介绍几个随机算法的例子
随机化快速排序算法
对于确定性快速排序算法,其平均时间复杂度,但是一定可以构造出至少一个对抗样例,使得每次快速排序选取的标准值都是当前区间内的最值,这样确定性快速排序算法的时间复杂度就会变为。
我们经过观测就会发现,确定性快速排序算法之所以会受到对抗样本的攻击,就是在选取标准值的时候,确定了选区位置,导致数据可以根据你的选取位置而调整数据的结构顺序,使算法永远处于最坏情况。这就如同几个人在玩扑克,如果有一家选择了明牌,那么其余玩家只需要仔细观察这位玩家手上的牌,然后针对其弱点规划自己的出牌顺序即可让自己的收益达到最大化,既然我们不想让这种情况发生,那么就要把明着的“牌”收起来。
解决办法
最简单的办法,在每一次取标准值的时候,随机在一个位置获取,这样就可以避免上述问题。
这就可以类似于,将每一个位置的数看成是一张扑克牌,选取随机一张牌,其实等价于将所有的牌打乱后在固定的位置获取一张牌,其时间复杂度可以较为容易的得出:。
这样我们对于构成的算法集合进行时间复杂度分析
但是我们将每一种算法的执行次数进行求和再求期望是十分不现实的事情,所以需要更换另外一个思路进行求解。
令数组当中表示数组S中的第i大个数,所以我们利用二项分布的思想,可以定义一个指示器随机变量
这时随机算法的执行次数T(A)就可以表示为
因此,根据期望的线性性质可以推出
对于随机选点过程,其实可构建成一个划分树,其中进行快速排序时最先选择的标准值作为划分树的根节点,其余元素与根节点比较。所以要想两个元素发生比较,唯一可行的情况就是两个元素的其中之一作为标准值被挑选出来,这样可以得出
故
这样就可以得出随机化快速排序算法的时间复杂度为。
随机算法分类
拉斯维加斯算法
算法永远会输出正确的结果,但是算法的运行时间是随机的,主要用来防止针对性的最坏时间复杂度情况的发生
蒙特卡洛算法
算法可能会输出错误结果,但是错误率是具有上界的,经过多次独立重复执行后会得出结果,但是需要注意如何整合多次执行的结果
两类随机算法的转化
拉斯维加斯算法---->蒙特卡洛算法
只需让一个拉斯维加斯算法在固定的时间停止,得到的蒙特卡洛算法的错误率上限由马尔可夫不等式求得
蒙特卡洛算法----->拉斯维加斯算法
如果存在一个快速验证解的方法时可以进行转化,只需要重复执行蒙特卡洛算法直到找到正确解即可。