随机算法:蒙特卡洛和拉斯维加斯算法
1 随机算法
随机性在计算机科学中的最初应用之一就是随机算法。随机算法是能够获得随机性来源(比如随机数生成器)的算法,它允许在很小的概率内出错。目前已经有许多问题我们知道怎样用随机算法高效地求解,而并不知道怎样用确定性算法(即不使用随机性的算法)高效求解。事实上,计算机科学中最重要的open problems之一就是询问每个高效的随机算法是否都有其对应求解相同问题的确定性算法。
下面是个简单的随机算法例子:
import numpy as np
def f(x):
y = np.random.binomial(1, 0.5)
if y == 0:
while x > 0:
print("What up?")
x -= 1
return x + y
对于一个确定的输入(比如),其输出可能会有差异,且其运行时间也可能有差异。那么对于一个随机算法,我们如何度量其正确性(correctness)和运行时间(running time)呢?事实上,如果我们要求它输出结果总是正确的,且运行时间总是,则它就是时间复杂度为的确定性算法了。
因此,对于随机算法它要么不是在所有情况下总是正确的,要么就不能保证运行时间总为,它可以看做是在正确性和运行时间之间做赌博(gamble)。
2 蒙特卡洛算法和拉斯维加斯算法
我们来看下面这个例子,给点个元素(为偶数)的序列,一半为一半为,我们想在想要找到一个含的序列下标。那么我们可以写出下面两个不同的算法:

我们将左边这种赌博时间但不赌博正确性的算法称为拉斯维加斯(Las Vegas)算法,右边这种赌博正确性但不赌博时间的算法为蒙特卡洛(Monte Carlo)算法。
如图所示的拉斯维加斯算法的失败概率,最坏运行时间无界,期望运行时间为(2次迭代);而如图所示的蒙特卡洛算法失败概率,最坏运行时间为。
总结一下,在我们上面这个问题中两个算法的区别如下表所示:
正确性 | 运行时间 | |
---|---|---|
确定性 | 总是正确 | |
蒙特卡洛 | 大概率正确 | |
拉斯维加斯 | 总是正确 | 大概率 |
下面给出蒙特卡洛算法和拉斯维加斯算法的形式化定义。
蒙特卡洛算法 设为一个可计算问题,为参数,为一个函数。若为一个随机算法,它使得
- 对任意,;
- 对任意,。
(注意此处的概率基于做出的随机选择)
则我们声称是一个能够以时间、的错误概率计算问题的蒙特卡洛算法。
拉斯维加斯算法 设为一个可计算问题,为一个函数。若为一个随机算法,它使得
- 对任意,(这里概率基于做出的随机选择);
- 对任意,。
则我们声称是一个能够以时间计算问题的拉斯维加斯算法。
3 蒙特卡洛算法实例:最小割(Min Cut)随机化算法
图割集是一个边的集合,当去掉这些边时将分为两个或多个连通部分。给定一个有个顶点的图,最小割问题就是在图中寻找一个基数最小的割集,也即找到非空子集使得从到的边数最小化。

接下来我们会介绍一个求解最小割算法的简单随机算法,该算法中重要的操作为边的缩减。
该算法包括次迭代(为顶点数目)。在每次迭代中,算法从图的现有边中均匀随机地选出一条边并将它缩减掉。在缩减边时,将两个顶点和合并成一个顶点,删除所有连接和的边,保留图中所有其他的边。新图可能有重边,但没有自环。
每一次迭代都会使图中的顶点数目减少一个,经过次迭代后,图中只剩下两个顶点。算法输出连接这两个保留顶点的边的集合。
下面我们来看在最小割集大小为的图中,两种最小割算法执行的例子。首先是成功运行的实例:

然后是不成功运行的实例:

现在我们来建立算法输出正确结果的概率的下界。
定理 算法至少以的概率输出最小割集。
证明 我们设集合为图的最小割集,除去集合后将顶点集合分为两个集合和,使得不存在连接中的顶点到中的边。我们在算法中缩减的边是中的顶点或中顶点的边,经次迭代后,算法输出的是由中边连接的两个顶点的图。所有,我们可以得到结论:如果算法在次迭代中根本不选择中的边,那么算法输出的就是最小割集。
设表示第次迭代时缩减的边不在中这一事件,表示在前次迭代中没有缩减中边的事件。我们需要计算的算法在次迭代中不选择中的边的概率,即为。
我们从计算开始。因为最小割集有条边,所以图中每个顶点至少连接条边(即度至少为),则根据握手定理图中至少有条边。第一次缩减的边是从所有边中均匀随机地选取的,故第一次迭代没有选取中边的概率为:
接下来,假设第一次缩减没有消去中的边,即给定了事件成立这一条件,那么我们在接下来的有个顶点的新图中也没有选取到中边的概率为:
类似地,我们有:
则
得证。
因为算法具有单边错误的性质,我们可以重复运行算法来减小出错率。假设运行最小割随机化算法次,并输出再所有迭代次中找到的最小长度割集。则输出不是一个最小割集的概率界为
在第一个不等式中,我们用到了经典不等式:。

4 拉斯维加斯算法实例:随机快速排序算法
快速排序是一种简单且实际上非常有效的排序算法。给定输入列表,随机快速排序算法可描述如下:
-
如果,返回;
-
均匀随机地选择基准(pivot);
-
将中每个其它元素与做比较,以将划分为两个子列表:, 。
-
递归地对和排序。
对于随机快速排序算法,我们有以下定理:
定理 假设在随机快速排序算法中,每一次都是从所有可能中独立且随机地选取基准,那么对于任意的输入,随机快速排序算法所做比较的期望次数为(这里的期望是关于基准的随机选取)。
证明 设与输入值有相同的值,但是按照升序排列。对,记为一随机变量,如果在算法执行过程的任何时候和进行了比较,则的值为,否则取。那么比较的总次数满足
且根据期望的线性性得
由于只是取和的示性随机变量,等于为1的概率。因此,我们接下来只需计算两个元素和相比较的概率即可。
现在,和相比较,当且仅当或是从集合中由随机快速排序算法选取的第一个基准。这是因为如果(或)是从这个集合选取的第一个基准,和必仍在同一个子列表中,因此它们将会进行比较。反之,如果两者都不是从这个集合中选取的第一个基准,那么和将会被分在不同的子列表中,所以不会进行比较。
因为我们的基准都是从每个子列表中独立且随机地选取的,也就是第一次从中选取的一个基准等可能地是这个集合中的任一元素。因此或是从中选取的第一个基准的概率(即取的概率)是。利用替换,得
注意第3个等式交换了双重求和的次序,这样就可以将内层求和直接用乘法表达出来,从而得到了期望的简洁形式。交换求和顺序的示意图如下所示:

又因为调和级数满足,因此,,得证。
参考
- [1] CMU 15-251: Great Ideas in Theoretical Computer Science: Lecture 19: Randomized Algorithms
- [2] Mitzenmacher M, Upfal E. Probability and computing: Randomization and probabilistic techniques in algorithms and data analysis(M). Cambridge university press, 2017.
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· spring官宣接入deepseek,真的太香了~