编程之美-金刚坐飞机问题

2024-03-17 14:58

本文主要是介绍编程之美-金刚坐飞机问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章背景


编程之美 4.1 “金刚坐飞机问题”的问题2,难度比问题1大很多。

编程之美的官方解法,包括原理分析、概率公式、推导过程等,感觉阐述不够详细,没有完全读懂。

搜索一下 “金刚坐飞机”,参考了几个很不错的分析,得到一个自己觉得比较完整的答案。

 

仔细审题

 

首先,仔细审题,有两个细节需要搞清楚:

 

  1. 飞机上总共有多少座位?N?N+1?还是更多?从问题1的官方解答看,飞机上座位总数为N。
  2. “...乘客们正准备按机票编号(1,2,3...N)依次排队登机。突然来了一只大猩猩(对,他叫金刚)。他也有飞机票,但是...”,金刚的机票编号是否属于闭区间[1,N]?换句话说,所有乘客(包括金刚)的总数是N还是N+1?既然座位总数为N,金刚也有飞机票,飞机也不可能超载,因此,所有乘客(包括金刚)的总数为N。金刚的机票编号也属于闭区间[1,N]。

 

 

推敲官方答案

 

然后,看一下编程之美的官方答案:第i个乘客坐在自己位置上的概率为 
 。
既然飞机座位总数为N,根据官方答案,第1个乘客的概率为。实际上,第1个乘客的概率应该为。计算过程如下:
根据全概率公式,第1个乘客坐在自己座位上的概率:


 
如何解释这个问题呢?从问题2的官方解答过程“如果n=1或n>i,那么第i个乘客坐在自己位置上的概率为1....”可以推测,官方认为金刚的机票编号为1。官方答案中的i应该不包括1。

 

重新描述问题

 

到这里,我重新描述一下问题:
飞机上有N个座位,座位编号依次为1,2,..N。恰好有N个乘客排队登机,第1个乘客的座位编号是1,第2个乘客的座位编号是2,...,第N个乘客的座位编号是N。每个乘客都应该坐在编号正确的座位上。但是,第1个乘客是不讲道理的金刚,他第一个进入飞机,随便(随机)挑了一个座位坐下。其他乘客敢怒不敢言,只好依次找座位坐下。如果自己的座位没有被占,则坐自己的作为,否则,也像金刚那样随便挑一个座位。现在,求第i个乘客(第1个乘客还是金刚)坐到自己座位的概率是多少?
我算出的答案为:


 
与官方答案是一致的,但是本文会给出更加详细的计算过程。

 

概率计算过程

 

下面描述计算过程。

令P(i)表示,第i个乘客坐到座位i的概率。

金刚的座位明明是空的,他还要随便占位;其他乘客只有在自己座位被占的情况下,才随便坐。因此,金刚与其他乘客的行为并不相同,需要分开计算。

 

先计算金刚的概率

 

显然,P(1)就是金刚坐在1号座位的概率。金刚是第一个随便挑座位的,因此概率为
 

 

再计算其他乘客的概率

核心工具是全概率公式

 

第2~N个乘客的概率不容易看出,我们根据全概率公式来计算,条件为金刚坐在编号为j的座位上:
,其中:

  • P(K=j)表示,金刚坐在座位j的概率
  • P(i|K=j)表示,在金刚坐在座位j上的情况下,第i个乘客坐在座位i的概率

显然,金刚坐在位置j的概率均等,都是

条件概率P(i|K=j)的计算不太直观,我们先简单分析一下:

  1. 如果j=1,也就是说金刚居然坐在了自己的座位上,第i个乘客(其实是所有其他乘客)必然能够坐到自己座位,因此P(K=j) = 1。
  2. 如果j=i,也就是说金刚居然坐在了第i个乘客的座位上,第i个乘客肯定不能坐到自己座位,因此P(K=j) = 0。
  3. 如果j>i,也就是说,金刚坐了(第i个乘客)后面的座位,不影响前面乘客找座位,第i个乘客(其实是第2~j-1个乘客)必然能够坐到自己座位,因此P(K=j) = 1。
  4. 如果1<j<i,也就是说,金刚抢了(第i个乘客)前面的座位,肯定会影响第i个乘客(其实是第j~N个乘客)的座位。

因此,可以初步计算:


这时,只需要计算最后一个条件概率

 

难点是计算条件概率

可以依次计算P(i|K=i-1),P(i|K=i-2),...,P(i|K=2),发现他们的值都为,神奇吧!

最终结果:


 

自顶向下计算条件概率

 

那么,1<j<i时,P(i|K=j)到底是怎么计算的呢?下面详细推导一下j=i-1和j=i-2这两种情况,其他情况可以顺推。

如果金刚坐在了座位i-1上,第i-1个乘客可以选择座位1、i、i+1~N。每种选择的概率均等,为1/(N-i+2):

 

  1. 如果第i-1个乘客选择座位1,则第i个乘客必然能坐到自己座位,概率为1
  2. 如果第i-1个乘客选择座位i,则第i个乘客必然不能坐到自己座位,概率为0
  3. 如果第i-1个乘客选择座位i+1~N,则第i个座位必然能坐到自己座位,概率为1

根据全概率公式,有

如果金刚坐在了座位i-2上,第i-2个乘客可以选择座位1、i-1、i~N。每种选择的概率均等,为1/(N-i+3):

 

  1. 如果第i-2个乘客选择座位1,则第i个乘客必然能坐到自己座位,概率为1
  2. 如果第i-2个乘客选择座位i-1,则第i-1个乘客的选择将影响第i个乘客的概率。此种情况恰好可以递归到P(i|K=i-1),只要假设第i-2个乘客就是金刚,它坐在了座位i-1上
  3. 如果第i-2个乘客选择座位i,则第i个乘客必然不能坐到自己座位,概率为0
  4. 如果第i-2个乘客选择座位i+1~N,则第i个座位必然能坐到自己座位,概率为1

根据全概率公式,有


 

如果继续计算下去,其实可以发现规律,
  

挖掘递归现象

 

其实,从上述推导的过程中,我们已经发现递归的迹象,是否可以再深入挖掘一下递归公式,进而避免繁琐的推导呢?

如果金刚坐在了座位j上,那么第j个乘客将会在座位1、j+1~N中随即选择一个座位。此时,乘客数量变成N-j+1,座位的数量也是N-j+1,第j个乘客恰好是剩余乘客的第1个,他变成了新的金刚。我们把他的座位编号从j换成1,这个变换不会影响问题的答案。下面我们来证明这个变换的安全性。

这个变换肯定会影响第j个乘客的概率,但是我们要计算的 并不包括第j个乘客,所以不用考虑这个影响。对于第2~i-1个乘客而言,如果第j个乘客无论是坐在1还是j,他们都可以坐在自己的座位上,对他们来说没有区别,对他们的概率也没有任何影响。因此,这个变换是安全的。

 

从问题的形式上看,变换之后的问题,与原问题等价,只是问题规模从N减小到N-j+1,且每位乘客的编号减小(j-1),座位编号也减小(j-1)。下面详细描述新问题:

飞机上有N-j+1个座位,座位编号依次为1,2,..N-j+1。恰好有N个乘客排队登机,第1个乘客的座位编号是1,第2个乘客的座位编号是2,...,第N-j+1个乘客的座位编号是N-j+1。每个乘客都应该坐在编号正确的座位上。但是,第1个乘客是不讲道理的金刚,他第一个进入飞机,随便(随机)挑了一个座位坐下。其他乘客敢怒不敢言,只好依次找座位坐下。如果自己的座位没有被占,则坐自己的作为,否则,也像金刚那样随便挑一个座位。现在,求第i个乘客(第1个乘客还是金刚)坐到自己座位的概率是多少?

 

利用递归形式计算条件概率

 

这里引入了一个新的变量n,表示乘客的总数。我们令F(i,n)表示在乘客总数为n的情况下,第i个乘客坐到自己座位的概率。显然,P(i) = F(i,N)。

下面,我们开始计算F(i,n),首先将P(i,N)计算结果中的N替换成n,然后利用子问题的递归形式。




 
 因此,我们有



 
 

结合金刚的概率,我们得到完整答案:

 

这篇关于编程之美-金刚坐飞机问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/819271

相关文章

springboot3.4和mybatis plus的版本问题的解决

《springboot3.4和mybatisplus的版本问题的解决》本文主要介绍了springboot3.4和mybatisplus的版本问题的解决,主要由于SpringBoot3.4与MyBat... 报错1:spring-boot-starter/3.4.0/spring-boot-starter-

在 Spring Boot 中使用异步线程时的 HttpServletRequest 复用问题记录

《在SpringBoot中使用异步线程时的HttpServletRequest复用问题记录》文章讨论了在SpringBoot中使用异步线程时,由于HttpServletRequest复用导致... 目录一、问题描述:异步线程操作导致请求复用时 Cookie 解析失败1. 场景背景2. 问题根源二、问题详细分

解读为什么@Autowired在属性上被警告,在setter方法上不被警告问题

《解读为什么@Autowired在属性上被警告,在setter方法上不被警告问题》在Spring开发中,@Autowired注解常用于实现依赖注入,它可以应用于类的属性、构造器或setter方法上,然... 目录1. 为什么 @Autowired 在属性上被警告?1.1 隐式依赖注入1.2 IDE 的警告:

解决java.lang.NullPointerException问题(空指针异常)

《解决java.lang.NullPointerException问题(空指针异常)》本文详细介绍了Java中的NullPointerException异常及其常见原因,包括对象引用为null、数组元... 目录Java.lang.NullPointerException(空指针异常)NullPointer

Android开发中gradle下载缓慢的问题级解决方法

《Android开发中gradle下载缓慢的问题级解决方法》本文介绍了解决Android开发中Gradle下载缓慢问题的几种方法,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、网络环境优化二、Gradle版本与配置优化三、其他优化措施针对android开发中Gradle下载缓慢的问

关于Nginx跨域问题及解决方案(CORS)

《关于Nginx跨域问题及解决方案(CORS)》文章主要介绍了跨域资源共享(CORS)机制及其在现代Web开发中的重要性,通过Nginx,可以简单地解决跨域问题,适合新手学习和应用,文章详细讲解了CO... 目录一、概述二、什么是 CORS?三、常见的跨域场景四、Nginx 如何解决 CORS 问题?五、基

MySQL安装时initializing database失败的问题解决

《MySQL安装时initializingdatabase失败的问题解决》本文主要介绍了MySQL安装时initializingdatabase失败的问题解决,文中通过图文介绍的非常详细,对大家的学... 目录问题页面:解决方法:问题页面:解决方法:1.勾选红框中的选项:2.将下图红框中全部改为英

Nginx启动失败:端口80被占用问题的解决方案

《Nginx启动失败:端口80被占用问题的解决方案》在Linux服务器上部署Nginx时,可能会遇到Nginx启动失败的情况,尤其是错误提示bind()to0.0.0.0:80failed,这种问题通... 目录引言问题描述问题分析解决方案1. 检查占用端口 80 的进程使用 netstat 命令使用 ss

mybatis和mybatis-plus设置值为null不起作用问题及解决

《mybatis和mybatis-plus设置值为null不起作用问题及解决》Mybatis-Plus的FieldStrategy主要用于控制新增、更新和查询时对空值的处理策略,通过配置不同的策略类型... 目录MyBATis-plusFieldStrategy作用FieldStrategy类型每种策略的作

linux下多个硬盘划分到同一挂载点问题

《linux下多个硬盘划分到同一挂载点问题》在Linux系统中,将多个硬盘划分到同一挂载点需要通过逻辑卷管理(LVM)来实现,首先,需要将物理存储设备(如硬盘分区)创建为物理卷,然后,将这些物理卷组成... 目录linux下多个硬盘划分到同一挂载点需要明确的几个概念硬盘插上默认的是非lvm总结Linux下多