@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 都是等概率生成的
三位二进制数中的每个数也是等概率生成的
000 | 0 |
---|---|
001 | 1 |
010 | 2 |
011 | 3 |
100 | 4 |
101 | 5 |
110 | 6 |
111 | 7 |
必备知识点
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;
}