动态规划问题(九)二项式系数计算

动态规划问题(九)二项式系数计算

问题描述

​ 给定两个正整数 n 和 r,求出它们二项式系数 \(\dbinom{n}{r}\)​ 的结果。

解决思路

​ 这个就是直接的公式套用就行,对于一般的 \(\dbinom{n}{k}\) (n > k,k > 0) 都有 $\dbinom{n}{k}=\dbinom{n - 1}{k - 1} + \dbinom{n - 1}{k} $ 对于 n== k 和 k = 0 的情况,\(\dbinom{n}{0} = \dbinom{n}{n} = 1\)

  • 递归方式
    • 由上文的公式,C(n, k) = C(n - 1, k - 1) + C(n - 1, k)。因此使用递归可以很简单地实现
    • 边界条件,对于 n == k 和 k == 0 的情况,结果都是 1;对于 k > n 的情况,得到的结果为 0
  • 动态规划
    • 由于递归调用会重复计算之前已经计算过的结果,因此可以使用动态规划来解决这类经典的重复子问题的问题
  • 公式
    • 一般的,\(\dbinom{n}{k} = \frac{n^k}{k!} = \frac{n(n-1)(n-2)\cdots(n-(k-1))}{k(k-1)(k-2)\cdots1}=\prod_{i=1}^k \frac{n + i - 1}{i}\)

实现

  • 递归

    public class Solution {
        public static long nCr(int n, int r) {
            // 边界条件
            if (r > n) return 0L; 
            if (n == r || r == 0) return 1L;
            
            return nCr(n - 1, r - 1) + nCr(n - 1, r);
        }
    }
    
  • 动态规划

    public class Solution {
        public static long nCr(int n, int r) {
            if (r > n) return 0L; 
            if (n == r || r == 0) return 1L;
            
            long[][] dp = new long[n + 1][r + 1];
            
            dp[0][0] = 1;
            for (int i = 1; i <= n; ++i) {
                for (int j = 0; j <= r; ++j) {
                    // 边界条件
                    if (i == j || j == 0) dp[i][j] = 1;
                    else dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j]; // 递推关系
                }
            }
            
            return dp[n][r];
        }
    }
    
  • 公式

    public class Solution {
        public static long nCr(int n, int r) {
            if (r > n) return 0L; 
            if (n == r || r == 0) return 1L;
    
            long ans = 1L;
            for (int i = 1; i <= r; ++i) {
                ans *= n - i + 1;
                ans /= i;
            }
    
            return ans;
        }
    }
    

posted @ 2021-08-18 10:09  FatalFlower  阅读(682)  评论(0编辑  收藏  举报