等概率问题(c++实现)

@TOC
前言 :

算法面试 不是给出正确答案,而是给出问题的思考方式。

概念

数据规模 :
一秒解决问题
O(n^2) 算法 可以解决 10 ^4 的问题
O(n) 可以解决 10^8 的问题
O(n log n ) 可以解决 10^ 7 的问题

多开一个辅助数组 :O(n)
多开一个辅助的二维数组:O (n^2)
递归调用是有空间代价的

在这里插入图片描述

等概率问题(二进制问题)

题目描述

给出一个随机函数可以等概率返回a-b,要求实现等概率返回c-d
在这里插入图片描述

思路分析:

先利用已知条件等概率得到0,1

f() 1, 2,3, 4, 5
错误思路: f() /5 的结果是 0 的概率为 80% ,1概率20%
f() 中 生成1, 2 输出0 生成4,5-输出1 则0,1概率分别为50%
f() ==3 则继续循环

核心:
利用二进制左右移操作得到任意数
二进制左移一位等于*2,右移=÷2

要想等概率得1-7 ,先等概率得到0-6 再+1

f() 可以等概率得到0,1;
利用3位数左移运算可以得到0-7
当结果为7继续循环,则可以等概率得到 0-6

0,1 都是等概率生成的
三位二进制数中的每个数也是等概率生成的

0000
0011
0102
0113
1004
1015
1106
1117

必备知识点

rand()和srand()

所在头文件: stdlib.h

(1)概念
要取得 [a,b) 的随机整数,使用 (rand() % (b-a))+ a;
要取得 [a,b] 的随机整数,使用 (rand() % (b-a+1))+ a;
要取得 (a,b] 的随机整数,使用 (rand() % (b-a))+ a + 1;
通用公式: a + rand() % n;其中的 a 是起始值,n 是整数的范围。
要取得 0~1 之间的浮点数,可以使用 rand() / double(RAND_MAX)。

rand()产生的随机数在每次运行的时候都是与上一次相同的,这样是为了便于程序的调试。 若要产生每次不同的随机数,则可以使用srand( seed )函数进行产生随机化种子,随着seed的不同,就能够产生不同的随机数。
(2) 使用

在这里插入图片描述

代码


#include<iostream>
#include <stdlib.h>
#include <time.h> 
using namespace std;
//等概率返回 1-5
int f(){
	return ( rand()%5 ) + 1;  //   随机返回1-5 
}
//等概率返回 0,1 
int ff(){
	
	int ans =0;
	do{
		ans = f();
	} while(ans==3); 
	return ans<3? 0:1;
}
//等概率返回0-6 
int fc(){
	int ans = 0;
	do{
		ans = (ff()<<2)+(ff()<<1)+(ff()<<0);    // 必须加括号 
	}while(ans==7);
	return ans;
} 
//等概率返回1-7 
int fd(){
	return fc()+1;
}
int main(){
	
	int arr[8]={0} ;    // 0-7  必须赋初值 
	srand((unsigned)time(NULL)); 
	int testTime=10000000;
	for(int i=0;i<testTime;i++){
	int ans = fd();
	arr[ans]++;	
	} 
	for(int i = 0 ;i < 8 ;i++){
		cout << i<<" :"<<  arr[i]<< endl;
	}	
	return 0;
} 

最终结果

在这里插入图片描述

相似题目

(1)

题目描述: 已知可以等概率返回7-13的任意一个数,求等概率返回26-39的任意一个数

思路:
在这里插入图片描述

(2)

题目描述: 随机函数f() 可以以p概率返回0,
1-p概率返回1,
要求等概率返回0和1;

在这里插入图片描述
思路分析 :

返回01 的概率 p * (1-p)
返回10 的概率(1-p) * p
当结果为00 或 11 时继续循环
代码:

#include <iostream>
#include<stdlib.h>
#include <time.h> 
using namespace std;
//内部不可见,自己定义 
//假设以0.8概率返回0,0.2概率返回1 
int f(){
	double tem= (rand() %11 )/10.0 ;
	return tem<0.8 ? 0:1;
} 
//等概率返回0,1 
int ff(){
	int ans =0;
	do{
		ans=f();
	} while(ans==f());//  当两次结果不一样时 结束循环 
	return ans; 
}


int main(){
	
srand((unsigned)time(NULL));    
int arr[2]={0};
int test =1000000; 
for(int i=0;i<test;i++){
	int ans =ff();
	arr[ans]++;
}
	cout << arr[0]<<","<< arr[1]<< endl;	
}

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值