一种求解组合数的思路

来源:互联网 发布:淘宝小号担保交易平台 编辑:程序博客网 时间:2024/05/13 09:34

组合数:从n个对象组成的集合中取出m个对象组成子集,组合数即为这种子集的个数,记为P(n,m)(和数学中表示不同,为了便于书写),0<=m<=n;

组合数的数学求解公式为: P(n,m)=(n!)/(m!*(n-m)!)

我们知道,一个数的阶乘随着这个数的的增长增长的很快,如果用int表示来存储阶乘的结果,到14的时候结果就溢出,就算用long long类型存储结果,到21时也会溢出,本文提供另一种求解组合数的思路;

最近在LeetCode里刷题,遇到一道题"Unique Paths",我的思路也是由此而来。我的解题思路是机器人从起点到终点需水平方向走n-1步,垂直方向走m-1步,所以总的路线数等于从m+n-2步中选择n-1步水平方向行走(其它m-1步垂直行走)的方法数,很显然用到组合数,线路数即等于P(m+n-2,n-1),然后套用数学公式求解。然而想法很美好,程序写好以后就面临了上述的溢出问题,这种方法以失败而告终。

然后学习别人的代码,看到了一种很好的算法,如下:

int uniquePaths(int m, int n) {if (m == 0 || n == 0)    return 0;vector<vector<int>> path(m, vector<int>(n, 1));int i = 0, j = 0;for (i = 1; i < m; ++i)    for (j = 1; j < n; ++j)        path[i][j] = path[i - 1][j] + path[i][j - 1];return path[m - 1][n - 1];}


该算法很好理解,即每个格子只能由它上面的格子(如果存在)垂直走一步,或者由它左边的格子(如果存在)水平走一步而到达,故到达当前格子的路径数等于到达它上面和左边格子路径数之和,以此迭代,最终求出到达目的地的路径数。这种算法的好处显而易见,避免了求解阶乘。

将上述两种算法进行结合,即可得到:

P(m+n-2,n-1)=uniquePaths(int m, int n)

这就为求解组合数提供了一种思路:

现在需求P(N,M)(为了区分,此处使用大写),令:

N=m+n-2

M=n-1

求解后代入即可得到:

P(N,M)=uniquePaths(N-M+1,M+1)

0 0
原创粉丝点击