LeetCode-5427、兩個盒子中球的顏色數相同的概率-困難

LeetCode-5427、兩個盒子中球的顏色數相同的概率-困難

桌面上有 2n 個顏色不完全相同的球,球上的顏色共有 k 種。給你一個大小爲 k 的整數數組 balls ,其中 balls[i] 是顏色爲 i 的球的數量。所有的球都已經 隨機打亂順序 ,前 n 個球放入第一個盒子,後 n 個球放入另一個盒子(請認真閱讀示例 2 的解釋部分)。請計算「兩個盒子中球的顏色數相同」的情況的概率。

注意:這兩個盒子是不同的。例如,兩個球顏色分別爲 a 和 b,盒子分別爲 [] 和 (),那麼 [a] (b) 和 [b] (a) 這兩種分配方式是不同的(請認真閱讀示例 1 的解釋部分)。

示例 1:

輸入:balls = [1,1]
輸出:1.00000
解釋:球平均分配的方式只有兩種:
- 顏色爲 1 的球放入第一個盒子,顏色爲 2 的球放入第二個盒子
- 顏色爲 2 的球放入第一個盒子,顏色爲 1 的球放入第二個盒子
這兩種分配,兩個盒子中球的顏色數都相同。所以概率爲 2/2 = 1 。

示例 2:

輸入:balls = [2,1,1]
輸出:0.66667
解釋:球的列表爲 [1, 1, 2, 3]
隨機打亂,得到 12 種等概率的不同打亂方案,每種方案概率爲 1/12 :
    [1,1 / 2,3], [1,1 / 3,2], [1,2 / 1,3], [1,2 / 3,1], [1,3 / 1,2], [1,3 / 2,1], 
    [2,1 / 1,3], [2,1 / 3,1], [2,3 / 1,1], [3,1 / 1,2], [3,1 / 2,1], [3,2 / 1,1]
然後,我們將前兩個球放入第一個盒子,後兩個球放入第二個盒子。
這 12 種可能的隨機打亂方式中的 8 種滿足「兩個盒子中球的顏色數相同」。
概率 = 8/12 = 0.66667

示例 3:

輸入:balls = [1,2,1,2]
輸出:0.60000
解釋:球的列表爲 [1, 2, 2, 3, 4, 4]。要想顯示所有 180 種隨機打亂方案是很難的,
但只檢查「兩個盒子中球的顏色數相同」的 108 種情況是比較容易的。
概率 = 108 / 180 = 0.6 。

示例 4:

輸入:balls = [3,2,1]
輸出:0.30000
解釋:球的列表爲 [1, 1, 1, 2, 2, 3]。要想顯示所有 60 種隨機打亂方案是很難的,
但只檢查「兩個盒子中球的顏色數相同」的 18 種情況是比較容易的。
概率 = 18 / 60 = 0.3 。

示例 5:

輸入:balls = [6,6,6,6,6,6]
輸出:0.90327

提示:

  • 1 <= balls.length <= 8
  • 1 <= balls[i] <= 6
  • sum(balls) 是偶數
  • 答案與真實值誤差在 10^-5 以內,則被視爲正確答案

 

代碼:

class Solution:
    def getProbability(self, balls: List[int]) -> float:
        k = len(balls)
        b1 = [None] * k
        b2 = [None] * k
        self.cnt = 0
        
        def calc(b):
            # s個球排列組合方案數
            s = sum(b)
            ans = math.factorial(s)
            for x in b:
                ans //= math.factorial(x)
            return ans
        
        def dfs(i):
            if i == k:
                if sum(b1) == sum(b2) and sum(b > 0 for b in b1) == sum(b > 0 for b in b2):
                    # 盒子b1與盒子b2中球的個數相同、顏色數相同
                    self.cnt += calc(b1) * calc(b2)
                return
            for j in range(balls[i] + 1):
                b1[i] = j
                b2[i] = balls[i] -  j
                dfs(i+1)
        dfs(0)
        tot = calc(balls)

        return self.cnt / tot

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章