一、背景知识
参考文章:组合数公式_百度百科
二、计算方法
参考文章:java实现求组合数C(n,k) 数学公式法和递归法_伤感的博客-CSDN博客_java 组合数公式
2.1 递推法
// C(n,m) 递推公式 C(n,m) = C(n-1,m-1) + C(n-1,m)
public int C(int n,int m){
if(m == 0 || m == 1) return 1;
// 利用性质 C(n,m) = C(n,n-m) 节省计算次数
if(m > n/2) m = n - m;
return C(n - 1,m - 1) + C(n - 1,m);
}
2.2 公式法
// C(n,m) = A(n,m)/m!, 其中A(n,m) = n*(n-1)*...*(n-m+1)
public int C(int n,int m){
// 利用性质节省计算量 C(n,m) = C(n,n-m)
if(m > n/2) m = n - m;
long a = 1; // 这次为了保证后面乘法运算不越界
long b = 1;
for(int i = 1;i <= m;i++){
// n*(n-1)*...*(n-m+1)
a *= (n - i + 1); // 这里即使long,也可能越界
// m!
b *= i;
}
return (int)a/b;
}
// 优化写法
public int C(int n,int m){
if(m > n/2) m = n - m;
long a = 1;
for(int i = 1;i <= m;i++){
a = a*(n - i + 1)/i;
// 注意: 以上语句写成 a *= (n-i+1)/i 会计算错误
// 知识点: *= 自动进行强制类型转换为左边的类型; a = a*b 不会进行强制类型转换
}
return (int)a;
}