目录
837. 新21点837. 新21点https://leetcode-cn.com/problems/new-21-game/
零、写在前面
今天是打卡的第30天,其实平心而论,今天的难度是不算高的。知识点在:
《算法零基础100讲》(第30讲) 概率与统计https://blog.csdn.net/WhereIsHeroFrom/article/details/121414040https://blog.csdn.net/WhereIsHeroFrom/article/details/121414040
一、主要知识点
1.动态规划
blablabla。。。。。看题吧,实在没啥知识点了-.-
二、课后习题
1227. 飞机座位分配概率
1227. 飞机座位分配概率https://leetcode-cn.com/problems/airplane-seat-assignment-probability/
题目描述
有 n 位乘客即将登机,飞机正好有 n 个座位。第一位乘客的票丢了,他随便选了一个座位坐下。
剩下的乘客将会:
如果他们自己的座位还空着,就坐到自己的座位上,
当他们自己的座位被占用时,随机选择其他座位
第 n 位乘客坐在自己的座位上的概率是多少?
思路
1.假如第一位直接坐在第一个 那么n必然坐在自己的位置上
2.假如第一位坐在第n个 那么n必然不坐在自己的位置上
3.假如第一位坐在第i个位置,那么就相当于第i个人随便找一个位置,第n坐在自己位置上的概率
可以得到概率公式
再坐下化简
最终得到
也就是F(n) =F(n-1)就是除了1全是1/2呗?
double nthPersonGetsNthSeat(int n){
return n == 1?1.0:0.5;
}
LCP 11. 期望个数统计
LCP 11. 期望个数统计https://leetcode-cn.com/problems/qi-wang-ge-shu-tong-ji/
题目描述
某互联网公司一年一度的春招开始了,一共有 n 名面试者入选。每名面试者都会提交一份简历,公司会根据提供的简历资料产生一个预估的能力值,数值越大代表越有可能通过面试。
小 A 和小 B 负责审核面试者,他们均有所有面试者的简历,并且将各自根据面试者能力值从大到小的顺序浏览。由于简历事先被打乱过,能力值相同的简历的出现顺序是从它们的全排列中等可能地取一个。现在给定 n 名面试者的能力值 scores,设 X 代表小 A 和小 B 的浏览顺序中出现在同一位置的简历数,求 X 的期望。
思路
如果能力值不同 一定是不同的 那么如果能力值相同呢?主要问题在这里
假如有n个相同的元素 假设第一个位置相同的概率就是1/n
那么总的E(X) = E(x1)*1/n+....=1
对,没错就是1.。。那么一切问题就简单了。统计有多少不同值元素不就好了,hash表。
int expectNumber(int* scores, int scoresSize){
int hash[1000001],len = 0;
for(int i = 0;i < scoresSize;i++)//hash初始化
hash[scores[i]] = 0;
for(int i = 0;i < scoresSize;i++)
if(!hash[scores[i]]) hash[scores[i]] = 1,len++;//统计元素
return len;
}
470. 用 Rand7() 实现 Rand10()
470. 用 Rand7() 实现 Rand10()https://leetcode-cn.com/problems/implement-rand10-using-rand7/
题目描述
已有方法 rand7 可生成 1 到 7 范围内的均匀随机整数,试写一个方法 rand10 生成 1 到 10 范围内的均匀随机整数。
不要使用系统的 Math.random() 方法。
思路
我们可以用两次rand7生成1-49的数字 就是(rand7-1)*7+rand7;
但是我们需要生成的是1-10,那么我们只取10-49这40个数字就好了。然后我们把它-6/4就能得到1-10。
int rand10() {
int a;
while(1){
a = (rand7()-1)*7 + rand7();
if(a<10) continue;//抛弃重随
else{
a = (a-6)/4;//修改映射
break;
}
}
return a;
}
1093. 大样本统计
1093. 大样本统计https://leetcode-cn.com/problems/statistics-from-a-large-sample/
题目描述
我们对 0 到 255 之间的整数进行采样,并将结果存储在数组 count 中:count[k] 就是整数 k 的采样个数。
我们以 浮点数 数组的形式,分别返回样本的最小值、最大值、平均值、中位数和众数。其中,众数是保证唯一的。
思路
这题不配叫做中等题。。。就按照定义求就完事了,能有啥技巧。
不过。。。平均数会溢出 我转成了long long
double* sampleStats(int* count, int countSize, int* returnSize){
double *ans = malloc(sizeof(double)*5);
ans[0] = 257;ans[1]=0;ans[2] = 0;
double zhongwei = 1;
int zhongshu = 1;
int size = 0;
*returnSize = 5;
for(int i = 0;i<countSize;i++){
if(count[i]){
if(i>ans[1]) ans[1] = i;//最大值
if(i<ans[0]) ans[0] = i;//最小值
ans[2] += (long long)i*count[i];
size += count[i]; //统计个数
if(count[i]>count[zhongshu]) zhongshu = i;//统计众数
}
}
ans[2] /= size; //平均数
//中位数求解
if(size&1 == 1){
int j = 0;
for(int i = 0;i<=size/2;){
i+=count[j++];
}
zhongwei = j-1;
}
else{
int i,j=0;
for(i = 0;i<size/2;){
i+=count[j++];
}
if(i>=size/2+1) zhongwei = j-1;
else {
zhongwei = j-1;
printf("%d ",j);
while(i<size/2+1) i+=count[j++];
printf("%d ",j);
zhongwei += j-1;
zhongwei/=2;
}
}
ans[3] = zhongwei;
ans[4] = zhongshu;
return ans;
}
剑指 Offer 60. n个骰子的点数
剑指 Offer 60. n个骰子的点数https://leetcode-cn.com/problems/nge-tou-zi-de-dian-shu-lcof/
题目描述
把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。输入n,打印出s的所有可能的值出现的概率。
你需要用一个浮点数数组返回答案,其中第 i 个元素代表这 n 个骰子所能掷出的点数集合中第 i 小的那个的概率。
思路
其实这道题很动态规划0.0
我们很容易知道第i次的点数范围是 i - 6*i;
考虑第i-1次 也就是前一次的点数,我们知道第i次掷色子只能是1-6 并且等可能都是1/6
那么假如第i-1次掷到了8那么可以为第i次之后掷色子的 9 、 10 、11 、12 、13 、14这六个数字贡献概率也也就是我们可以遍历第i-1次所有的结果概率得到第i次的概率
double* dicesProbability(int n, int* returnSize){
double *ans = malloc(sizeof(double)*6*n);
for(int i = 0;i < 6;i++) ans[i] = 1.0/6.0;
for(int i = 2;i <= n;i++){
double temp[i*5+1]; //临时数组
for(int j=0;j<i*5+1;j++) temp[j] = 0.0;
for(int j = 0;j<i*5-4;j++)
for(int k = 0;k<6;k++)
temp[j+k] += ans[j]/6;//计算第i次的概率分布
for(int j = 0;j<i*5+1;j++)//计算第i次的概率分布
ans[j] = temp[j];
}
*returnSize = n*5+1;//i - 6*i 一共有5*i+1个数字
return ans;
}
837. 新21点
837. 新21点https://leetcode-cn.com/problems/new-21-game/
题目描述
爱丽丝参与一个大致基于纸牌游戏 “21点” 规则的游戏,描述如下:
爱丽丝以 0 分开始,并在她的得分少于 K 分时抽取数字。 抽取时,她从 [1, W] 的范围中随机获得一个整数作为分数进行累计,其中 W 是整数。 每次抽取都是独立的,其结果具有相同的概率。
当爱丽丝获得不少于 K 分时,她就停止抽取数字。 爱丽丝的分数不超过 N 的概率是多少?
思路
其实这道题和上面那道题的思路有点像。
我们要求的是F(0)
但是我们知道F(K)-F(K+W)的值 因为[F(k) , F(N)] = 1 然后大于N概率就是0
逆向一下 我们可以知道F(K-1)的值 因为 F(k-1) = 1/W*F(K)+....1/W*F(K+W-1)
根据这种递推关系 我们就可以退出来F(0)
为了加快速度,,,不然超时,我们可以用一个sum保存当前计算元素的前W项的和
double new21Game(int n, int k, int maxPts){
double dp[k+maxPts],sum = 0;
for(int i = k;i < k+maxPts;i++) //初始化最前端的位置
if(i <= n) dp[i] = 1.0,sum+=1.0;
else dp[i] = 0.0;;
for(int i = k -1;i>=0;i--){//递归计算
dp[i] = sum/maxPts;
sum = sum - dp[i+maxPts] + dp[i];
}
return dp[0];//返回
}
1467. 两个盒子中球的颜色数相同的概率
题目描述
桌面上有 2n 个颜色不完全相同的球,球上的颜色共有 k 种。给你一个大小为 k 的整数数组 balls ,其中 balls[i] 是颜色为 i 的球的数量。
所有的球都已经 随机打乱顺序 ,前 n 个球放入第一个盒子,后 n 个球放入另一个盒子(请认真阅读示例 2 的解释部分)。
思路
其实就是算将2n个球分为两堆 两堆颜色数目相同的概率
全集我们很容易知道 就是 可以拆解为
然后符合条件的元素我们就需要进行拆解先看第一个球 我们就可以拆解成
然后我们就可以递归调用 直到F中第一个参数等于n判断是否满足条件即可
为了加速 我们做两个小改动
1.用left数组保存剩余球数目,如果剩余球的数目小于两个袋子球数之差就直接返回
2.提前计算阶乘加速计算排列数
int left[8];
int n = 0;
long long f[11] = {1,1,2,6,24,120,720,5040,40320,362880,3628800}; //阶乘
int combination(int a,int b){
return f[b]/(f[a]*f[b-a]);
}
double dfs(int* balls,int m,int leftnum,int leftcol){//m为递归深度 也就是第几种颜色 leftnum表示前一个口袋比后一个口袋多多少球 leftcol表示前一个口袋比后一个口袋多多少颜色
if(m == n)
return leftnum ==0 && leftcol == 0;//保证球数差为0且颜色差为0
if(abs(leftnum) > left[m]) //始终无法满足 直接跳出
return 0;
double ans = 0;
for(int i = 0;i <= balls[m];i++){ //计算所有情况
int color = (i == 0) ? -1 : (i == balls[m] ? 1 : 0);//简单来说 i为0的时候颜色差为负数,i为最大值的时候颜色差为正数 其他时候为0 因为每个口袋都分到这种颜色的球了
ans += (combination(i,balls[m]))*dfs(balls,m + 1,leftnum +i - (balls[m] - i),leftcol + color);
}
return ans;
}
double getProbability(int* balls, int ballsSize){
n = ballsSize;
int sum = 0;
for(int i = 0;i < n;i++)//计算总数
sum += balls[i];
left[n-1] = balls[n-1];//初始化剩余球数
for(int i = n - 2;i >= 0;i--)
left[i] = balls[i] + left[i + 1];
double q = 1.0;
for(int i = 1;i <= sum/2;i++)
q *= (sum/2 + i)*1.0/i;//计算C(n,2*n)
return dfs(balls,0,0,0)/q;
}
写在最后
今天看了英雄哥的话感觉受益匪浅,卷完这周的刷题,下周我就要有安排的补充知识点了,慢慢的形成体系,当然需要先有量暴露问题,然后才能更有针对性的解决。我看好多人都很迷茫,其实就是先去尝试做些事情,做着做着才能发现问题,才能思考怎么取改进,只是迷茫是没有任何帮助的,好了,大家加油呀!