WriteUp - 日常编码问题(8)

WriteUp - 日常编码问题(8)

硬币翻转'!

改天,又一个问题要解决!

与往常一样,有两个免责声明:

  • 这些问题由精彩的时事通讯 Daily Coding Problem 提供,您可以订阅 这里 .查看并尝试解决您的挑战!
  • 我不是专业的程序员,只是一个喜欢分享他试图解决这些问题的最佳镜头的人。

它是第 8 号,这一次问题最初是由 Microsoft 提出的。让我们看看问题!

你有 n 公平的硬币,你同时翻转它们。任何出现的人都放在一边。出现的尾巴你再次翻转。在只剩下一枚硬币之前,您预计要玩多少轮?

写一个函数,给定 n , 返回在剩下一枚硬币之前您希望玩的回合数。

这次我们正在处理一些统计数据。这个问题要求我们按照所提出的规则计算在我们期望用一枚硬币剩下多少轮之后。之后,我们应该编写一个函数来进行计算。

让我们从一些数学开始,然后我们将编写问题提出的简单解决方案!

数学

在开始写任何算法之前,我们需要了解一些数学知识。

具体来说:我们如何预测每一次抛硬币的结果,以了解我们还有多少正面可以再次抛?

简短的回答:我们不能。

如果硬币( C , 从现在开始) 是公平的, 他们有 1/2 的机会出现正面 ( H , 从现在开始) 和另外 1/2 的机会出现 Tails ( ,从现在开始):这样就不可能准确地猜测结果会是什么。

我们可以做的是尝试 估计结果会​​是什么 ,通过使用的概念 期望值 (E),常见于许多统计领域。我不会对此进行深入探讨,但基本上我们可以通过以下示例恢复它:

假设您在赌场下注,平均而言,人们在玩游戏的 2/3 次中赢得 60 美元,但在其余时间他们也可能输掉 90 美元。

现在,很明显,我们无法确切知道我们是否会赢。我们能做的是计算期望值 ** ** 结果的 ** 是的** ,只需将事件的概率乘以它们的值,然后加在一起。所以基本上:

Expected value equation

所以这场比赛的预期结果是 10:平均而言,我们希望从这场比赛中赢得 10 美元。

我们也可以在我们的游戏中使用这个概念:我们可以计算出预期的 H 数。这将告诉我们在抛硬币时预期有多少 H。

首先,我们需要计算我们的硬币的可能结果 C 实际上是,它们的概率是多少。当我们两者都有时,我们可以简单地计算 H 在折腾中,通过差异,价值 .

这里有一些例子:

Calculations of probabilities of coin tosses

请注意,对于我们开始的每个硬币数量,正面的期望值,以及反面的差异, 将永远是初始硬币的一半 .老实说,这可能是一个非常幼稚的想法:由于我们使用的是公平硬币,我们预计它们正面和反面的概率是 1/2,因此我们也可以预期每次抛硬币正面和反面的概率为 1/2 1/2 硬币在尾巴上。

但是为什么会这样呢?

想一想:以 5 个硬币盒为例。连续得到 5 个正面的概率,就像连续得到 5 个反面的概率一样,非常低(1/32)。现在想想连续获得 50 个正面的机会(1/1,12589990684e+15):这基本上是不可能的。

相反,在更合理的情况下概率会增加,例如连续获得 2 或 3 个正面(在 5 个硬币的情况下为 10/32),将正面和反面分成两半。从技术上讲,这里的概率分布类似于正态分布,也称为 高斯分布 .当我们增加硬币的数量时,我们会得到类似这样的东西(x 轴显示硬币的数量)。

Gaussian distribution of probability over coin toss from 1 to 50 coins

由于最可能的结果集中在分布的中间,我们预计在每次抛硬币时,我们都会将硬币减半。

但是奇数个硬币呢?例如,如果我们有 5 个硬币,拆分它们意味着在下一回合获得 2.5 个反面。这怎么可能?发生这种情况是因为投掷的不确定性。 由于我们有奇数个硬币,这意味着我们将在我们的抛掷中得到正面比反面多 1 个或反面比正面多 1 个。 最后一枚硬币的概率仍然是 1/2。因此,2.5 意味着我们预计剩下 2 个正面、2 个反面和 1 个硬币,我们无法真正预测结果。

那么我们在这里做什么呢?没什么特别的: 我们继续减半,直到剩下 E(T) = C - E(H) 当我们真的确定我们只剩下一枚硬币时,它等于或大于 1。

算法

这么简单的算法有这么多词!话不多说,解决方法如下:

 def tossCounter(硬币): 剩余尾巴 = 硬币  
 轮数计数器 = 0 而剩余的尾巴> 1:  
 roundsCounter += 1  
 剩余尾数 = 剩余尾数/2 返回回合计数器

我们首先定义我们的函数 投掷计数器 和两个变量:

  • 剩余的尾巴 ,它将保留我们剩余的尾巴以供下一次抛掷;
  • 回合计数器 ,它会记录我们投掷的总次数。

之后,用一个简单的 尽管 循环,我们遍历 剩余的尾巴 加 1 回合计数器 对于每次折腾和减半 剩余的尾巴 为下一轮。

我们只是返回 回合计数器 最后,这将等于只剩下一枚硬币之前的总抛掷次数。

请注意,我们也可以使用日志计算解决方案,但我想避免使用 Python 数学库或其他库,以使代码尽可能简单。如果您想尝试,请记住除 C 一次又一次地除以 2 直到我们得到 1,这就像将它除以 2 的幂 X, 这将是我们在以一枚硬币结束之前必须玩的回合数。

Reduction to logarithms

时间复杂度

和往常一样,让我们​​在这里简要了解一下我们的时间复杂度。这个时间相当简单,因为唯一耗时的代码块是 while 循环,它一直运行到我们将硬币数量减半为止。这意味着它的时间复杂度取决于我们传递给算法的硬币数量,因此它在 O(n) 时间内运行。

所以,这是我对这个问题的看法。你怎么看待这件事?如果您有更好的解决方案,请告诉我,我将很高兴学习应对此类挑战的新方法。

我要感谢您阅读整篇文章:如果您喜欢,请给我鼓掌或评论,那真的会让我很开心!我每次都尝试发布这样的挑战,包括 IT 相关和编程内容,所以如果您有兴趣,请关注博客!

而且,如果您不喜欢它,仍然非常感谢您阅读到最后:让我知道如何改进它!

感谢您的阅读,一如既往,

尼古拉

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明

本文链接:https://www.qanswer.top/36384/50391410

posted @ 2022-09-14 10:52  哈哈哈来了啊啊啊  阅读(12)  评论(0编辑  收藏  举报