首先介绍一点数学知识。
事件 A 的指示器随机变量I{A}定义为:
I{A}={1如果A发生0如果A不发生
指示器随机变量的期望为:
E[I{A}]=Pr{A},其中Pr{A}为事件A发生的概率。
期望性质:期望的和等于和的期望,即若X=∑Xi, 则E[∑Xi]=∑E[Xi]
雇佣问题:输入长度为n的数组 A[0, …, n-1], 其元素数值代表每个人的能力。假定初始时助手的能力为0, 且每次遇到能力高于当前助手能力的人,便辞掉当前助手,并雇佣该人. 每次雇佣需要花费费用ch,求总费用。
图示:假设 A = [2, 1, 3].
在上述例子中,一共雇佣了两次助手,花费为2ch.
上述过程的代码如下:
int hire( vector<int>& A){
int now_ability = 0;
int cost = 0;
for( auto it : A)
if( it > now_ability){
now_ability = it;
cost++;
}
return cost;
}
在上述代码中我们并不关注时间复杂度,反而关注雇佣费用。
最坏情况下,即数组 A 按顺序递增时,花费最大,为数组所有元素的和。
下面来关注雇佣问题中,雇佣一个新助理的期望。
假定应聘者已随机顺序出现,Xi对应第 i 人被雇佣,其指示器随机变量为:
Xi=I{第i位被雇佣}={1第i位被雇佣0第i位未被雇佣
在源代码中,若第 i 个人被雇佣,则意味着第 i 人比第 1~n-1人都优秀。又假定应聘者随机出现,所以前i个应聘者也按照随机次序出现,因此被认为前 i 中任何一个人都是等可能是目前最优秀的人,因此Pr[xi]=i1.
又因E[I{A}]=Pr{A}, 因此E[I{Xi}]=i1.
则令X=∑i=1nXi, 有
E[I{X}]=i=1∑ni1=1+21+...+n1
由调和级数的性质可知,上式结果为:
E[I{X}]=lnn+O(1)
即,面试了 n 个应聘者,平均意义上也只雇佣了lnn个人。