Randomized algorithms(随机算法)
随机算法是由一个雇佣问题引出的:
假如你要雇佣一名新的办公室助理,但是你先前的雇佣尝试都失败了,你打算找一个雇佣代理。雇佣代理每天给你推荐一个应聘者。你面试这个人,然后决定是否雇佣他,同时你需要付给雇佣代理一定的费用,以便面试应聘者。除此之外,雇佣一个人也需要花费一大笔钱,因为你必须辞掉目前的办公室助理,同时付给雇佣代理一大笔中介费。
你承诺:任何时候都找最合适的人来担任这项职务,因此你决定在面试完应聘者之后,如果该应聘者比目前的办公室助理更合适,就会辞掉当前的办公室助理,然后聘用新的。
同时你愿意为该策略付费,但希望能够估算出该费用。
下面先给出HIRE-ASSISTANT过程的伪代码,该伪代码表示雇佣策略。
假设应聘候选人编号为1…n,该过程中,假设你能在面试完应聘者i之后,可以决定应聘者i是否为你目前见过最佳的人选。
HIRE-ASSISTANT
best = 0
for i = 1 to ninterview candidate iif candidate i is better than bestbest = ihire candidate i
不管是分析费用,还是分析运行时间,采用的方法都是相同的。在任何情形中,我们都是在计算特定基本操作的执行次数。
例如,面试和雇佣都会产生一定的费用,面试费用较低,比如cic_ici,然后雇佣的费用很高,比如chc_hch。假设以用有n个应聘者,m个被雇佣的人,那么这个算法的总费用为O(cin+chm)O(c_in+c_hm)O(cin+chm)。由于面试产生的费用总是cinc_incin,因此我们只关注分析chmc_hmchm就可以了,也就是雇佣的费用。
我们很容易就知道,上述的策略是极其依赖于输入序列的,不同的输入序列,会产生不同的情况,运行时间也就不同。如果应聘者的质量严格递增的话,你就需要雇佣n次,总的费用就是O(chn)O(c_hn)O(chn)。这个时候我们就需要讨论平均情况下的运行时间了,我们可以假设每个应聘者是随机出现的。随机出现就意味着所有应聘者之间存在着一个全序关系,那么一共就有n!n!n!种排列的可能,每一种序列等概率出现。
但是大多数情况下,我们并不知道应聘者是不是随机出现的,因此这个时候可以在输入和算法之间加入一个随机数生成器,那么这个时候我们可以称这个算法是随机的。(在实践中,大多数编程环境会提供一个伪随机数生成器,它是一个确定性算法,返回值在统计上看起来是随机的。)
当分析一个随机算法的运行时间时,我们以运行时间的期望值来衡量,一个随机算法的运行时间称为期望运行时间;当概率分布发生在算法的输入的时候,我们讨论的是平均情况运行时间。
指示器随机变量
我们经常采用指示器随机变量来进行分析,它为概率和期望之间的转换提供了一个便利的方法。
给定一个样本空间SSS和一个事件AAA,那么事件AAA对应的指示器随机变量I(A)I(A)I(A)定义为:
I{A}={1如果A发生0如果A不发生I\{A\}= \left \{ \begin{aligned} &1 \quad \text{如果A发生}\\ &0 \quad \text{如果A不发生} \end{aligned} \right. I{A}={1如果A发生0如果A不发生
举个例子,假设我们来确定抛一枚标准硬币时 正面朝上的期望次数。样本空间S={T,F}S=\{T \,, F\}S={T,F},TTT表示正面朝上,FFF表示反面朝上,其中Pr{T}=Pr{F}=1/2Pr\{T\}=Pr\{F\}=1/2Pr{T}=Pr{F}=1/2。接下来定义一个指示器随机变量XTX_TXT,对应硬币朝上的事件TTT。这个变量是计数抛硬币时正面朝上的次数,如果正面朝上则值为1,否则为0。
XT=I{T}={1如果T发生0如果F发生X_T=I\{T\}= \left \{ \begin{aligned} &1 \quad \text{如果T发生} \\ &0 \quad \text{如果F发生} \end{aligned} \right. XT=I{T}={1如果T发生0如果F发生
所以在一次抛硬币的时候,正面朝上的期望次数就是指示器变量XTX_TXT的期望值:
E[XT]=E[I{T}]=1∗Pr{T}+0∗Pr{F}=1/2E[X_T]=E[I\{T\}]=1*Pr\{T\}+0*Pr\{F\}=1/2 E[XT]=E[I{T}]=1∗Pr{T}+0∗Pr{F}=1/2
因此,抛一枚硬币的时候,正面朝上的期望次数为1/21/21/2。
一个事件A对应的指示器随机变量的期望值等于事件A发生的概率。
给定一个样本空间S和事件A,设XA=I{A}X_A=I\{A\}XA=I{A},那么E[XA]=Pr{A}E[X_A]=Pr\{A\}E[XA]=Pr{A}。(这里就不证明了,证明过程可以去看算法导论)
指示器随机变量看起来很麻烦,但是在分析重复随机试验的时候是非常有用的。
接下来我们使用指示器随机变量来分析这个雇佣问题。
XXX对应我们雇佣新的办公室助理的次数,XiX_iXi对应第iii个应聘者被雇佣 这个指示器随机变量:
Xi=I{i被聘用}={1应聘者i被聘用0应聘者i未被聘用X_i=I\{i\text{被聘用} \}= \left \{ \begin{aligned} &1 \quad \text{应聘者}i\text{被聘用} \\ &0 \quad \text{应聘者}i\text{未被聘用} \end{aligned} \right. Xi=I{i被聘用}={1应聘者i被聘用0应聘者i未被聘用
X=X1+X2+...+XnX=X_1+X_2+...+X_n X=X1+X2+...+Xn
现在我们分析一下HIRE-ASSISTANT执行的效率:
我们在上文已经假设每个应聘者是随机出现的,那么前iii个应聘者中的任意一个都等可能的是目前最有资格的,那么应聘者iii比其他应聘者更有资格的概率是1/i1/i1/i,也就是应聘者iii会以1/i1/i1/i的概率被雇佣。
E[Xi]=Pr{应聘者i被雇佣}=1/iE[X_i]=Pr\{\text{应聘者}i\text{被雇佣}\}=1/i E[Xi]=Pr{应聘者i被雇佣}=1/i
E[X]=E[∑i=1nXi]=∑i=1nE[Xi](期望的线性性质)=∑i=1n1/i=ln(n)+O(1)(调和级数)\begin{aligned} E[X] &= E[\sum_{i=1}^{n}X_i] \\ &=\sum_{i=1}^n E[X_i] \quad \text{(期望的线性性质)} \\ &=\sum_{i=1}^n 1/i \\ &=ln(n)+O(1) \quad \text{(调和级数)} \end{aligned} E[X]=E[i=1∑nXi]=i=1∑nE[Xi](期望的线性性质)=i=1∑n1/i=ln(n)+O(1)(调和级数)
根据上述分析的结果,我们可以知道,尽管我们需要面试nnn个人,但平均起来,实际上大约只雇佣了他们之中的ln(n)ln(n)ln(n)个人。
假设应聘者是随机次序的,那么算法HIRE-ASSISTANT总的雇佣费用平均情况下为O(chlnn)O(c_hlnn)O(chlnn)。
我们之前也说过,我们不能限制输入的随机性,但是我们可以加一个中间层,不管输入的序列是什么,都产生一个均匀随机的序列,这样执行就不依赖于输入了,而是依赖于随机选择。
RANDOMZED-HIRE-ASSISTANT
randomly permute the list of candidates//随机输入
best = 0
for i = 1 to ninterview candidate iif candidate i is better than bestbest = ihire candidate i
我们只是做了一个简单的改变,很明显看出,这个随机算法的性能,与假设应聘者以随即次数出现所得结果是一样的。因为和之前相比,只是去掉了假设,换成了使用随机算法使输入随机化。
很多随机算法通过给定输入 变换排列以使输入随机化。接下来讨论两种随机方法,并给予证明。(我用我贫瘠的数学知识,我太废了)
第一种:为数组的每个元素A[i]A[i]A[i]赋予一个随机的优先级P[i]P[i]P[i],然后根据优先级对数组AAA中的元素进行排序。就是我们常说的置换策略。
例如:A={1,2,3,4}A=\{1,2,3,4\}A={1,2,3,4},随机的优先级P={45,23,96,12}P=\{45, 23, 96, 12\}P={45,23,96,12}(数值越小,优先级越高),那么就会产生一个数组B={4,2,1,3}B=\{4,2,1,3\}B={4,2,1,3}。这个过程称为PERMUTE-BY-SORTING:
PERMUTE-BY-SORTING
n = A.length
let P[1...n] be a new array
for i = 0 to nP[i]=RANDOM(1,n^3)
sort A, using P as sort keys
这里使用n3n_3n3是为了让PPP中所有的优先级尽可能唯一,现在假设所有的优先级都唯一。
那接下来我们证明这个过程能产生一个均匀随机排列,即该过程可以等可能地产生数字1~n的每一种排列。换种说法就是,需要证明每一种排列发生的概率是1n!\frac{1}{n!}n!1。
先考虑每个元素A[i]A[i]A[i]分配到第iii个的特殊排列开始,其实就是A=BA=BA=B。假设EiE_iEi代表元素A[i]A[i]A[i]分配到第iii个这个事件,则对所有的iii,该事件发生的概率是:
Pr{E1∩E2∩⋅⋅⋅∩En−1∩En}=Pr{E1}∗Pr{E2∣E1}∗Pr{E3∣E2∩E1}⋅⋅⋅Pr{En∣En−1∩⋅⋅⋅∩E1}\begin{aligned} &Pr\{E_1 \cap E_2 \cap···\cap E_{n-1} \cap E_n\} \\ \\ &=Pr\{E_1\}*Pr\{E_2|E_1\}*Pr\{E_3|E_2 \cap E_1\}···Pr\{E_n|E_{n-1}\cap···\cap E_1\} \end{aligned} Pr{E1∩E2∩⋅⋅⋅∩En−1∩En}=Pr{E1}∗Pr{E2∣E1}∗Pr{E3∣E2∩E1}⋅⋅⋅Pr{En∣En−1∩⋅⋅⋅∩E1}
其中Pr{E1}Pr\{E_1\}Pr{E1}是从一个nnn个元素的集合中选取一个优先级最高(即数值最小)的概率,那么Pr{E1}=1/nPr\{E_1\}=1/nPr{E1}=1/n。Pr{E2∣E1}Pr\{E_2|E_1\}Pr{E2∣E1}就是从剩下的n−1n-1n−1个元素中选取一个优先级最高的概率,那么Pr{E2∣E1}=1/(n−1)Pr\{E_2|E_1\}=1/(n-1)Pr{E2∣E1}=1/(n−1)。以此类推,Pr{Ei∣Ei−1∩...∩E1}=1/(n−i+1)Pr\{E_i|E_{i-1}\cap...\cap E_1\}=1/(n-i+1)Pr{Ei∣Ei−1∩...∩E1}=1/(n−i+1)。因此,
Pr{E1∩E2∩⋅⋅⋅∩En−1∩En}=(1n)(1n−1)...(1n−i+1)...(12)(11)=1n!Pr\{E_1 \cap E_2 \cap···\cap E_{n-1} \cap E_n\}=\bigg( \frac{1}{n} \bigg) \bigg( \frac{1}{n-1} \bigg)...\bigg( \frac{1}{n-i+1} \bigg)...\bigg( \frac{1}{2} \bigg)\bigg( \frac{1}{1} \bigg)=\frac{1}{n!} Pr{E1∩E2∩⋅⋅⋅∩En−1∩En}=(n1)(n−11)...(n−i+11)...(21)(11)=n!1
现在已经证明这个特殊的排列的发生的概率是1n!\frac{1}{n!}n!1,现在需要扩展到其他的排列。如果EiE_iEi代表元素A[i]A[i]A[i]分配到第ξ(i)\xi(i)ξ(i)小的事件,A[i]A[i]A[i]被分配到了jjj位置上,上述的证明同样适用。因此,如果要计算得到任何特定排列的概率,该计算与前面的计算完全相同,于是得到此排列的概率为1n!\frac{1}{n!}n!1。
这样我们就证明了PERMUTE-BY-SORTING过程可以产生输入的均匀随机的排列。
第二种方法,就是原地排列给定数组。在进行第iii次迭代的时候,元素A[i]A[i]A[i]是从元素A[i]A[i]A[i]到A[n]A[n]A[n]中随机选取的,第iii次迭代之后,A[i]A[i]A[i]不再改变。 RANDOMIZE-IN-PLACE过程的时间复杂度为O(n)O(n)O(n)。
RANDOMIZE-IN-PLACE
n = A.length
for i = 1 to nswap A[i] with A[RANDOM(i,n)]
接下来我们我们来证明这个过程可以产生均匀随机排列,和之前一样,证明每个排列生成的概率为1n!\frac{1}{n!}n!1,证明方位使用的是循环不变式。
循环不变式和数学中的数学归纳法一样,都是一种演绎推理法,用于理解和证明算法的正确性。
循环不变式不是一个狭义上的一个式子,而是一个命题,在算法的起始状态、运行过程中和算法而技术时始终保持为真的一个命题。
循环不变式的三条性质:
初始化
:循环的第一次迭代之前,它为真。
保持
:如果循环的某次迭代之前它为真,那么下次迭代之前它仍为真。
终止
:在循环终止时,不变式为我们提供一个有用的性质,该性质有助于证明算法时正确的。注意:循环不变式的前两条性质类似于数学归纳法,证明了一个基本情况和一个归纳步。此外,终止性不同于数学归纳法的做法,在归纳法中,归纳步是无限地使用的,这里当循环终止的时候,归纳随之终止。
对于RANDOMIZE-IN-PLACE,在进行第iii迭代之前,对每个可能的(i−1)(i-1)(i−1)排列(有(n−i+1)!(n-i+1)!(n−i+1)!种),那么在子数组A[1...i−1]A[1...i-1]A[1...i−1]包含某个(i−1)(i-1)(i−1)排列的概率为(n−i+1)!/n!(n-i+1)!/n!(n−i+1)!/n!。
我们只需要证明,该循环不变式在第1次迭代之前为真,同时循环的每次迭代能够维持此不变式,并且当循环终止时,这个不变式能够得到证明算法正确的有用性质或结果。
初始化: 在第1次迭代之前,此时i=1i=1i=1,对于循环不变式来说,子数组A[1...0]A[1...0]A[1...0]包含0排列的概率为n!/n!=1n!/n!=1n!/n!=1。我们很容易知道,子数组A是一个空数组,0排列也是空的,没有元素,那么该子数组包含0排列的概率必然为1。因此,该循环不变式在第一次迭代之前是为真的。
保持: 我们假设在进行第iii次迭代之前,每种可能的(i−1)(i-1)(i−1)排列出现在子数组A[1...i−1]A[1...i-1]A[1...i−1]中的概率为(n−i+1)!/n!(n-i+1)!/n!(n−i+1)!/n!。我们要证明在第iii次迭代之后,每种可能的iii排列出现在子数组A[1...i]A[1...i]A[1...i]中的概率为(n−i)!/n!(n-i)!/n!(n−i)!/n!,依然保持循环不变式。
我们先考虑一个特殊的iii排列,{x1,x2,...,xi}\{x_1,x_2,...,x_i\}{x1,x2,...,xi},这个排列中包含一个(i−1)(i-1)(i−1)排列 {x1,x2,...,xi−1}\{x_1,x_2,...,x_{i-1}\}{x1,x2,...,xi−1},接着算法会在A[i]A[i]A[i]中放入xix_ixi。
设E1E_1E1表示前i−1i-1i−1次迭代已经在A[1...i−1]A[1...i-1]A[1...i−1]中构造了(i−1)(i-1)(i−1)排列的事件,根据循环不变式,Pr{E1}=(n−i+1)!/n!Pr\{E_1\}=(n-i+1)!/n!Pr{E1}=(n−i+1)!/n!。
设E2E_2E2表示第iii次迭代在位置A[i]A[i]A[i]放置xix_ixi的事件。当E1E_1E1和E2E_2E2都恰好发生的时候,{x1,x2,...,xi}\{x_1,x_2,...,x_i\}{x1,x2,...,xi}排列会出现在A[1...i]A[1...i]A[1...i]中,因此:
Pr{E2∩E1}=Pr{E2∣E1}∗Pr{E1}=1n−i+1∗(n−i+1)!n!=(n−i)!n!\begin{aligned} Pr\{E_2\cap E_1\}=Pr\{E_2|E_1\}*Pr\{E_1\}=\frac{1}{n-i+1}*\frac{(n-i+1)!}{n!}=\frac{(n-i)!}{n!} \end{aligned} Pr{E2∩E1}=Pr{E2∣E1}∗Pr{E1}=n−i+11∗n!(n−i+1)!=n!(n−i)!
这符合循环不变式。
终止: 终止的时候,i=n+1i=n+1i=n+1,子数组A[1...n]A[1...n]A[1...n]是一个给定n排列的概率为(n−(n+1)+1)/n!=1!/n!=1(n-(n+1)+1)/n!=1!/n!=1(n−(n+1)+1)/n!=1!/n!=1。
综上所述,RANDOMIZE-IN-PLACE可以产生一个均匀随机排列。
从上面一大堆我们可以知道,随机算法使得算法不再依赖于输入,通常是解决一个问题最简单、最有效的方法。
Randomized algorithms(随机算法)相关推荐
- 算法设计技巧与分析(八):随机算法(Randomized Algorithms)
文章目录 随机算法(Randomized Algorithms) 一.随机选择(Randomized Selection) 二.测试字符串相等性(Testing String Equality) 三. ...
- [题集]ADS13 Randomized Algorithms
1.Let a=(a1,a2,-,ai,-,aj,-,an) denote the list of elements we want to sort. In the quicksort algor ...
- [PKUWC2018]随机算法
题意:https://loj.ac/problem/2540 给定一个图(n<=20),定义一个求最大独立集的随机化算法 产生一个排列,依次加入,能加入就加入 求得到最大独立集的概率 loj25 ...
- Dubbo中基于权重的随机算法
转载自dubbo源码解析-LoadBalance dubbo的源码地址:https://github.com/alibaba/dubbo Dubbo中的RandomLoadBalance采用基于权重的 ...
- labuladong的算法小抄pdf_随机算法:水塘抽样算法
读完本文,你可以去力扣拿下如下题目: 382.链表随机节点 398.随机数索引 -----------我最近在 LeetCode 上做到两道非常有意思的题目,382 和 398 题,关于水塘抽样算法( ...
- 算法导论之概率分析和随机算法
在问题的分析中应用概率技术称为概率分析,前期是对所有可能的输入集合可以做假定.如果无法对输入分布做合理性建模,如果一个算法的行为不只是由输入决定,同时也由随机数生成器所产生的数值决定,则为随机算法.行 ...
- java 权重_java实现权重随机算法
权重随机算法在抽奖,资源调度等系统中应用还是比较广泛的,一个简单的按照权重来随机的实现,权重为几个随机对象(分类)的命中的比例,权重设置越高命中越容易,之和可以不等于100: 简单实现代码如下: im ...
- 使用轮转算法求时间片_彩票调度算法,让进程们拼手气? --当操作系统遇上随机算法...
这篇文章主要想介绍下彩票调度(个人觉得这个算法非常有意思~ ),还有随机算法相对传统算法的一点优势,毕竟现在绝大多数算法都是追求确定性,尤其在操作系统,大家都希望一切可控,所以随机算法的出现听起来有些 ...
- 浅浅地谈一下随机算法【poj2454】【poj3318】
随机算法我也只是稍微接触了一下,就是想写篇博客自己稍微总结一下 其实随机算法也算是一个玄学吧,运气不好还是会wa.但是我们知道,计算机可以在短时间内计算大量的数据,所以碰到正确答案的概率还是挺大的. ...
最新文章
- 寒冰linux视频教程笔记8 系统监控
- 网络营销外包立足用户角度完成企业网站网络营销外包优化
- PHP 安全问题入门:10 个常见安全问题 + 实例讲解
- Python列表的常用方法
- 直播报名 | 用户中台建设实践解析
- 人生财富值得珍藏的文字
- 【图嵌入】Graph Embedding 方法之 LINE 原理解读
- java学习(60):java最终类(了解)
- 解决VM虚拟机中ubuntu系统上不了网的问题
- 波卡生态DAO基础设施完成150万美元战略融资
- mysql闩_Oracle闩:Cache Buffers chains
- python 中关于系统路径的事项;
- PMP中英文术语对照
- 【jq练习】基本选择器
- 【win10压缩卷问题解决】:无法将卷压缩到超出任何不可移动的文件所在点
- 卡西欧计算机设置参数,【卡西欧 fx-991CN X 中文函数计算器使用总结】参数|功能|显示|计算_摘要频道_什么值得买...
- 清梦_飘云羽逸_新浪博客
- 2009.7.30-8.4生活小结
- (三)对图像进行Gauss高斯平滑处理
- pandas中的concat操作