力扣每日一刷Day 26

Practice Day twenty-six:Leetcode T 62

噢吼吼,今天的Leetcode居然有图看,这么美味的图,居然是免费的吗!?

今天来品尝品尝组合数学吧,其实就是高中知识,简单的很,放高考纯送分题

核心思想:

这是一道典型的组合数学问题,即二项式定理
要从 (0, 0) 到 (m-1, n-1),总共需要走 (m-1 + n-1) 步,其中选择 (m-1) 步向下,其余为向右。

所以总路径数是:

C(m+n−2,m−1)

或者等价地:

C(m+n−2,n−1)

这就是所有理论了,有些小弟弟小妹妹还没上高中的可以先去B站学一下组合数学的知识,应该五分钟就可以学会了,这里我就不再使用过多篇幅描述了。

鉴于题目十分简单,理论十分简单,所以代码实现也十分简单,我这里就直接放出代码吧

class Solution {
public:
    int uniquePaths(int m, int n) {
        long long ans = 1;
        for (int x = n, y = 1; y < m; ++x, ++y) {
            ans = ans * x / y;
        }
        return ans;
    }
};

使用long long定义ans是为了防止溢出

对于for循环那部分

for (int x = n, y = 1; y < m; ++x, ++y) {
    ans = ans * x / y;
}
  • 变量解释

    • x:从 n 开始递增,表示组合数中的分子项。
    • y:从 1 开始递增,表示分母项。
    • 每次循环都进行 ans = ans * x / y,即逐步计算组合数。
    • 且y<m,使得最终y到达的是m-1,那么y增大了m-2个单位大小,则x到达的是n+m-2

为什么要逐步计算组合数?
在计算组合数(如 C(n, k))时,如果直接使用阶乘计算:

会出现以下几个问题:

1. 数值太大,容易溢出

  • 在 C++ 中,int 的最大值是约 2.1e9,long long 是约 9e18。
  • 当 n 很大时,比如 n=5050! 是一个非常大的数(约 3e64),远远超过 long long 的范围。
  • 直接计算阶乘会导致整数溢出,结果变成错误的负数或零。

2. 计算效率低

  • 阶乘的计算需要很多次乘法操作,尤其是当 n 很大时。
  • 而且,即使你用 long long,也可能会因为数值太大而无法正确存储。

但是这样会出现一个问题:怎么保证这样做不会每次都能整除?要知道C++中的int不能整除可是会进行截断的!

这是因为我们算法的设计

for (int x = n, y = 1; y < m; ++x, ++y) {
    ans = ans * x / y;
}

每一步的计算都是组合数,而组合数不会出现非整数。

今天的组合数学到此为止

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值