5.1 雇用问题
一. 雇用问题
1. 问题描述
假设雇用一名新的办公助理,先找一名雇用代理。雇用代理每天推荐一个应聘者,雇用者决定是否雇用。雇用者必须给雇用代理一小笔费用,以便面试应聘者。在面试完每个应聘者后,如果该应聘者比目前的办公助理更合适,就会辞掉当前的办公助理,然后聘用新的。
HIRE-ASSISTANT
过程表示雇用策略。假设应聘办公助理的候选人编号为
1
1
1 到
n
n
n 。该过程中假设雇用者在面试完应聘者
i
i
i 后,决定应聘者
i
i
i 是否是你目前见过的最佳人选。初始化时,该过程创建一个虚拟的应聘者,编号为
0
0
0 ,他比所有的应聘者都差。
HIRE-ASSISTANT(n)
best = 0 // candidate 0 is a least-qualified dummy candidate
for i = 1 to n
interview candidate i
if candidate i is better than candidate best
best = i
hire candidate i
面试的费用较低,比如为 c i c_i ci ,然而雇用的费用较高,设为 c h c_h ch 。假设 m m m 是雇用的人数,那么该算法的总费用就是 O ( c i n + c h m ) O(c_in+c_hm) O(cin+chm) 。不管雇用多少人,总会面试 n n n 个应聘者,于是面试产生的费用总是 c i n c_in cin 。因此我们只关注于分析 c h m c_hm chm ,即雇用的费用。这个量在该算法的每次执行中都不同。
2. 最坏情况分析
在最坏情况下,应聘者质量按出现的次序严格递增时,雇用了 n n n 次,总的费用是 O ( c h n ) O(c_hn) O(chn) 。
3. 概率分析
对所有可能输入产生的运行时间取平均。当报告此种类型的运行时间时,我们称其为平均情况运行时间。
所有应聘者存在一个全序关系,可以使用从
1
1
1 到
n
n
n 的唯一号码对应聘者排列名次,用
r
a
n
k
(
i
)
rank(i)
rank(i) 表示应聘者
i
i
i 的名次,并照常约定一个较高名次对应一个更好的应聘者。有序序列
<
r
a
n
k
(
1
)
,
r
a
n
k
(
2
)
,
.
.
.
,
r
a
n
k
(
n
)
>
<rank(1), rank(2), ... ,rank(n)>
<rank(1),rank(2),...,rank(n)> 是序列
<
1
,
2
,
.
.
.
,
n
>
<1,2,...,n>
<1,2,...,n> 的一个排列。称应聘者以随机顺序出现,等价于称这个排名列表是数字
1
1
1 到
n
n
n 的
n
!
n!
n! 种排列表中的任一个。或者,我们也称这些排名构成一个均匀随机排列;也就是说,在这
n
!
n!
n! 种可能的排列中,每一种以等概率出现。
4. 随机算法
如果一个算法的行为不仅由输入决定,而且也由随机数生成器产生的数值决定,则称这个算法是随机的。
假设有一个可以自由使用的随机数生成器 RANDOM
,调用 RANDOM(a, b)
将返回一个介于
a
a
a 和
b
b
b 之间的整数,并且每个整数以等概率出现。每次 RANDOM
返回的整数独立于前面调用的返回值。
分析一个随机算法的运行时间时,我们以运行时间的期望值衡量,其中输入值由随机数生成器产生。我们将一个随机算法的运行时间称为期望运行时间。一般而言,当概率分布是在算法的输入上时,我们讨论的是平均情况运行时间;当算法本身做出随机选择时,我们讨论其期望运行时间。
二. 练习
5. 1-1
证明:假设在过程 HIRE-ASSISTANT
的第
4
4
4 行中,我们总能决定哪一个应聘者最佳,则意味着我们知道应聘者排名的全部次序。
证明:偏序关系要求自反、反对称、传递,次序关系为
R
R
R ,对任意应聘者
a
,
b
,
c
a,b,c
a,b,c,
a
R
b
aRb
aRb 表示
a
a
a 排名相对
b
b
b 相同或是更优,于是:
自反:
a
R
a
aRa
aRa
传递:如果
a
R
b
aRb
aRb 且
b
R
c
bRc
bRc 则
a
R
c
aRc
aRc
反对称:如果
a
R
b
aRb
aRb 则
b
R
a
bRa
bRa 不一定成立
于是
R
R
R 为一偏序关系。由于我们假设总能比较任意两个应聘者,于是我们总能决定哪一个应聘者最佳,则意味着我们知道应聘者排名的全部次序。
*5. 1-2
请描述 RANDOM(a, b)
过程的一种实现,他只调用 RANDOM(0, 1)
。作为
a
a
a 和
b
b
b 的函数,你的过程的期望运行时间是多少?
解:伪代码如下:
RANDOM(a, b)
range = b - a
bits = ceil(log(2, range))
result = 0
for i = 1 to bits
r = RANDOM(0, 1)
result = result + r >> i
if result > range
return RANDOM(a, b)
else return a + result
记
k
=
⌈
lg
(
b
−
a
)
⌉
k = \lceil\lg(b-a)\rceil
k=⌈lg(b−a)⌉ ,则 RANDOM(0, 1)
共运行了
k
k
k 次,RANDOM(a, b)
期望运行次数为
2
k
b
−
a
\frac{2^k}{b-a}
b−a2k 。期望运行时间
Θ
(
2
k
b
−
a
k
)
\Theta(\frac{2^k}{b-a}k)
Θ(b−a2kk) 。由于
2
k
<
b
−
a
2^k<b-a
2k<b−a ,从而运行时间为
O
(
k
)
O(k)
O(k) 。
*5. 1-3
假设你希望以
1
/
2
1/2
1/2 的概率输出
0
0
0 与
1
1
1 。你可以自由使用一个输出
0
0
0 或
1
1
1 的过程 BIASED-RANDOM
。它以某概率
p
p
p 输出
1
1
1 ,概率
1
−
p
1-p
1−p 输出
0
0
0 ,其中
0
<
p
<
1
0<p<1
0<p<1 ,但是
p
p
p 的值未知。请给出一个利用 BIASED-RANDOM
作为子程序的算法,返回一个无偏的结果,能以概率
1
/
2
1/2
1/2 返回
0
0
0 ,以概率
1
/
2
1/2
1/2 返回
1
1
1 。作为
p
p
p 的函数,你的算法的期望运行时间是多少?
解:调用两次 BIASED-RANDOM
的结果可能为
00
,
01
,
10
,
11
00,01,10,11
00,01,10,11 ,我们定义如下策略:
00
00
00 或
11
11
11 :再调用两次 BIASED-RANDOM
01
01
01 :输出
0
0
0
10
10
10 :输出
1
1
1
于是, P r { 00 ∣ 11 } = p 2 + ( 1 − p ) 2 Pr\{00|11\}=p^2+(1-p)^2 Pr{00∣11}=p2+(1−p)2 , P r { 01 } = P r { 10 } = p ( 1 − p ) Pr\{01\}=Pr\{10\}=p(1-p) Pr{01}=Pr{10}=p(1−p)
由于没有其他方式返回 0 0 0 或 1 1 1 。因此返回 0 0 0 与 1 1 1 的概率为 1 / 2 1/2 1/2 。
伪代码如下
UNBIASED-RANDOM
while true
x = BIASED-RANDOM
y = BIASED-RANDOM
if x != y
return x
此方案的预期试验次数是 1 / 2 p ( 1 − p ) 1/2p(1-p) 1/2p(1−p) ,于是预期运行时间是 Θ ( 1 / 2 p ( 1 − p ) ) \Theta(1/2p(1-p)) Θ(1/2p(1−p)) 。