n passengers board an airplane with exactly n seats. The first passenger has lost the ticket and picks a seat randomly. But after that, the rest of passengers will:
- Take their own seat if it is still available,
- Pick other seats randomly when they find their seat occupied
What is the probability that the n-th person can get his own seat?
Example 1:
Input: n = 1
Output: 1.00000
Explanation: The first person can only get the first seat.
Example 2:
Input: n = 2
Output: 0.50000
Explanation: The second person has a probability of 0.5 to get the second seat (when first person gets the first seat).
Constraints:
1 <= n <= 10^5
這道題說是有n個人要登機,且飛機上正好有n個座位,說是第一個人會在n個座位中隨機選一個位置坐,然后從第二個人開始,遵循這樣的選座方法:若其對應的座位號是空的,則坐到自己的位置,否則就在剩余的位置中隨機挑選一個位置坐,現在問第n個人能坐到自己的位置的概率是多少。這道題其實沒有太多的算法在里面,本質上其實是一道數學題,一般來說這種類似腦筋急轉彎的題目在數學推導方面完成了之后,代碼可能就非常的簡單了,甚至一兩行就可以搞定了,但難點就是在於數學推導的部分。現在來分析一下吧,由於第一個人是隨機挑選座位,其挑選的座位對后面的人的影響是不同的,需要分情況來討論:
-
當第一個人正好選到了自己的座位時,這種情況的概率是
1/n,那么對於之后的所有人來說,自己的座位都是空的,可以直接坐,那么每個人坐到自己位子的概率也就是第一個人坐到自己位置的概率,都為1/n(包括第n個人)。 -
當第一個人直接一勾子坐到第n個座位上(概率是
1/n),那么不管中間的人怎么坐,第n個人都無法再坐到自己的位置上了,概率為0。 -
當第一個人坐到了范圍 [2, n-1] 中的任意一個位置,共有的 n-2 個位置可供選擇,到達這種情況的總概率是
(n-2)/n,但坐到每一個位子的概率還是1/n。若第一個人坐到了第二個位子,第二個人此時就有三種選擇:1)坐到第一個人的位子,則之后所有的人都可以坐到自己的位子了,包括第n個人,概率是(n-2)/n * 1/(n-2)。2)坐到第n個座位,則第n個人就無法坐自己位子了,概率是0。3)坐其他的座位,范圍是 [1, 1] 並 [3, n-1],這里還是得分情況討論,有沒有沒發現,這三種情況其實就是對應着第一個人開始的三種情況,也就是說當前實際上就變成了一個共 n-1 個座位的子問題,此時第二個人就相當於變成了第一個人,但可能有的童鞋會有疑問,不對吧,此時的第二個人不能坐自己的位置,而第一個人開始是可以坐自己的位置的,兩人的情況不同啊,怎么能說是子問題呢?其實看是不是子問題,主要是看對所求的結果是否有影響,求的只是第n個人能坐到自己位置的概率,即便第二個人不能坐自己的位置,但是可以坐第一個人的位置,那么就相當於前兩個人都坐了自己的位置,對后面的人沒有影響,所以可以看作是子問題,這種情況的概率是(n-2)/n * 1/(n-2) * f(n-1)。當第一個人坐到第三個位子的時候,那么第二個人就可以坐自己的位置,第三個人實際又面臨相同的三個選擇,此時就是共有 n-2 個座位的子問題, 這種情況的概率是(n-2)/n * 1/(n-2) * f(n-2),后面都是依次類推。
所以,整個的概率可以寫為如下表達式:
f(n) = 1/n + 0 + (n-2)/n * (1/(n-2) * f(n-1) + 1/(n-2) * f(n-2) + ... + 1/(n-2) * f(2))
化簡一下可得:
f(n) = 1/n + 1/n * (f(n-1) + f(n-2) + ... + f(2))
注意這是n大於2的情況,n小於等於2的時候,可以直接分析出來,就是 0.5。現在的目標是要化簡上面的表達式,首先兩邊同時乘以n,可以得到:
n * f(n) = 1 + f(n-1) + f(n-2) + ... + f(2)
把上面這個稱作公式1,然后將上面公式中的n用 n-1 替換,可以得到公式2:
(n-1) * f(n-1) = 1 + f(n-2) + f(n-3) + ... + f(2)
然后用公式1減去公式2,可以得到:
n * f(n) - (n-1) * f(n-1) = f(n-1)
化簡后可得:
f(n) = f(n-1)
我們已經知道 f(2) = 0.5,那么根據上面這個式子,就可以知道任何大於2的n的函數值都是 0.5,所以這道題也就一行代碼搞定了,參見代碼如下:
class Solution {
public:
double nthPersonGetsNthSeat(int n) {
return n == 1 ? 1.0 : 0.5;
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/1227
參考資料:
https://leetcode.com/problems/airplane-seat-assignment-probability/
