概率分析和随机算法

雇用问题描述

一个老板想换掉自己的办公助理,并且决定每次面试一个人,如果当前这个面试者比现在的办公助理好,就雇用他,并且解聘现在的办公助理。

描述成伪代码可以有如下形式:

Hire-Assistant(n):
best = 0	//假装有最菜的面试者,其实也可以理解为当前助理最菜
for i=1 to n	//遍历全部面试者
	interview candidate i	//取当前面试者
	if candidate i is better than candidate best	//判断谁更优秀
		best = i	//改变best指的人
		hire candidate i	//雇用面试者i

总共要面试 n 个面试者, 这期间可能会雇用 m 个人,也就是换人换了 m 次。
假设面试一次花费 c 块 ,雇用一个人需要 h 块 ,那么我们可以知道:
面试全部人费用为 C* n ,且这个是固定的。
最后雇用花的费用为 h*m,这个是不确定的。
这时候我们不知道 雇用行为 会出现多少次,这就涉及到概率行为。

概率分析

太多数情况下,我们用概率分析来分析一个算法的运行时间。例如上面 Hire-Assistant中的雇用费用。 为了进行概率分析,我们必须使用或者假设关于输入的分布。 然后分析这个算法,对输入产生的运行时间取平均。在这个问题中可以是对雇用次数取平均或者雇用花费取平均,实际问题实际分析。 我们称这个为平均情况运行时间。

均匀随机队列:面试者出现次序是均匀随机的,每个序列概率都是相等的。

随机算法

如果一个算法的行为不仅由输入决定,还由随机数生成器决定,我们就称这个算法是随机的。 我们假设有一个可以自由使用的随机数生成器 RANDOM(a,b) ,调用它将会等概率返回一个介于 a 和 b 间的整数。在大多数环境中的随机数算法都是这种伪随机数生成器,返回值在统计上看起来是随机的。

当分析一个随机算法的运行时间时,其中输入值由随机算法产生,则运行时间称为期望运行时间

思考
考虑 RANDOM(a,b)实现,只能调用RANDOM(0,1)

  • a 和 b 中有 b - a + 1个数
  • RANDOM(a,b)也就是 a + RANDOM(0,b - a + 1)
  • 找二进制里 刚好大于 b - a - 1 的数 ,2m >= b - a - 1, 取 m 位
  • m位二进制位都由 RANDOM(0,1)生成,若是比 b - a + 1 大,舍掉就行
#include <iostream>
#include <stdlib.h>
#include <ctime>
using namespace std;

//随机生成 0 | 1
int random_0_1()
{
	return rand() % 2;
}
//获得刚好大于 b - a + 1 的二进制位数
int getBit(int a, int b)
{
	int n = b - a + 1;
	int bit = 0;
	int value = 1;
 
	while (value < n)
	{
		bit++;
		value = value << 1;
	}
	return bit;
}
 //具体实现
int random_a_b(int a, int b)
{
	int bit = getBit(a, b);
 
	int flag;
	int result = 0;
	while (true)
	{
		for (int i = 0; i < bit; i++)
		{
			flag = random_0_1();//二进制位置位
			flag = flag << i; //左移到那个位置
			result |= flag;	//取或
		}
 
		if (result + a > b)
		{
			result = 0;
			continue;
		}
		else
			break;
	}
	
	return result + a;
}
 
int main()
{
	srand(unsigned(time(NULL)));
	
	for (int i = 0; i < 100; i++)
	{
		int result = random_a_b(5, 10);
		cout << "result: " << result << endl;
	}
}

再思考
假设生成 0 的概率为 p,生成1的概率为1-p,怎么制造 RANDOM(a,b)。

设想该生成器随机生成两个数,有下面四种组合:

组合概率
00p2
01p*(1-p)
10p*(1-p)
11(1-p)2

所以能发现 10 和 01 等概率出现,我们令 10 为1 ,01 为0,就能回到上一个思考题做法。

再再思考
已知有个rand7()的函数,返回1到7随机自然数,让利用这个rand7()构造rand10() 随机1~10。
其实还是想办法找相等概率的数来组合,但是在这里是以和的形式。
令A = rand7 = {1,2,3,4,5,6,7}
令B = (rand7-1)*7 = {0,7,14,21,28,35,,42}
有没有发现什么? A和B中每个元素的概率都是 1/7 ,并且相加后能出现 1~49,在这里构造rand10()只需要舍去 41~49再取余就行了。

指示器随机变量

给定一个样本空间 S 和一个事件 A,那么事件A对应的指示器随机变量 I {A}即:
在这里插入图片描述
是不是和我们抛硬币一个道理。

雇用问题与指示器

我们可以定义 n 个变量,分别对应每个面试者是否被雇用。假设 Xi 对应于第 i 个面试者被雇用的指示器随机变量,则有:
在这里插入图片描述

而且有 X = X1 + X2 + X3 + … + Xn
在这里插入图片描述

当看到前 i 个人时,第 i 个人比 i-1那个优秀的概率 为 1/i ,所以:
在这里插入图片描述
最后可以得出 E(X)
在这里插入图片描述
也就是大约 雇用了 ln(n)个人。

参考书籍
《算法导论》

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值