"Sword Finger Offer" Brush Question Series-(62) the number of n dice points

topic

Throw n dice on the ground, and the sum of the points on the upward side of all dice is s. Enter n to print out the probability of all possible values ​​of s.
You need to use an array of floating-point numbers to return the answer, where the i-th element represents the probability of the i-th smallest in the set of n dice that can be rolled.

Input: 2
Output: [0.02778,0.05556,0.08333,0.11111,0.13889,0.16667,0.13889,0.11111,0.08333,0.05556,0.02778]

Ideas

Dynamic programming solution.
When there are n dice, the minimum value of the sum of points is n, and the maximum value is n*6.
Create a two-dimensional array with n rows and 6n columns, dp [i] [j] represents i dice, the number of points and the number of occurrences of j.
When there is only one dice, the points and possible situations are 1, 2, 3, 4, 5, 6, and the number of each occurrence is 1.
When adding a dice, the number of points that this dice appears is also from 1 to 6, and the probability of appearance is the same. When the sum of points is s, the new dice appears 1, the old dice points are s-1, the new dice points are 2, and the old dice points are s-2,.... So at this time the number of points and the number of appearances of s is the sum of the number of appearances of (s-1), (s-2), (s-3), (s-4), (s-5), (s-6) .
The range of the points and s of the two dice is from n=2 to n*6=18.

Insert picture description here

Code

class Solution:
    def twoSum(self, n: int) -> List[float]:
        dp = [[0 for _ in range(6*n+1)] for _ in range(n+1)]
        for j in range(1,7):
            dp[1][j]=1
        
        for i in range(2,n+1):
            for j in range(i,6*i+1):
                for s in range(1,7):
                    if j-s<0: break
                    dp[i][j]+=dp[i-1][j-s]
        
        res=[]
        for i in range(n,6*n+1):
            res.append(dp[n][i]/(6**n))
        return res


optimization

The space complexity of the above algorithm is O(n*n), but there will be a lot of space that is not used or used once and is no longer used. So think of ways to optimize from space complexity.
We find that the data of the nth dice is solved by the data saved by the first n-1 dice. Therefore, you only need to know the result of the last time for each solution. We apply for a one-dimensional array, and each time we add a dice, we update the value from right to left in the array. Note that in each round of update, you need to initialize the first position in the array to 0.

Code

class Solution:
    def twoSum(self, n: int) -> List[float]:
        dp = [0 for _ in range(6*n+1)]
        for j in range(1,7):
            dp[j]=1
        
        for i in range(2,n+1):
            for j in range(6*i,i-1,-1):
                dp[j]=0
                for s in range(1,7):
                    if j-s<i-1: break
                    dp[j]+=dp[j-s]
                    
        res=[]
        for i in range(n,6*n+1):
            res.append(dp[i]/(6**n))
        return res

the complexity

Before optimization:
Time complexity: O(n^2)
Space complexity: O((n+1)(6n+1))=O(n^2)

After optimization:
Time complexity: O(n^2)
Space complexity: O(n)

Guess you like

Origin blog.csdn.net/weixin_44776894/article/details/107509128