zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Leetcode.2400 恰好移动 k 步到达某一位置的方法数目

方法 移动 位置 数目
2023-09-14 09:01:26 时间

题目链接

Leetcode.2400 恰好移动 k 步到达某一位置的方法数目 Rating : 1751

题目描述

给你两个 整数 startPosendPos。最初,你站在 无限 数轴上位置 startPos处。在一步移动中,你可以向左或者向右移动一个位置。

给你一个正整数 k,返回从 startPos出发、恰好 移动 k步并到达 endPos不同 方法数目。由于答案可能会很大,返回对 1 0 9 + 7 10^9 + 7 109+7 取余 的结果。

如果所执行移动的顺序不完全相同,则认为两种方法不同。

注意:数轴包含负整数。

示例 1:

输入:startPos = 1, endPos = 2, k = 3
输出:3
解释:存在 3 种从 1 到 2 且恰好移动 3 步的方法:

  • 1 -> 2 -> 3 -> 2.
  • 1 -> 2 -> 1 -> 2.
  • 1 -> 0 -> 1 -> 2. 可以证明不存在其他方法,所以返回 3 。

示例 2:

输入:startPos = 2, endPos = 5, k = 10
输出:0
解释:不存在从 2 到 5 且恰好移动 10 步的方法。

提示:

  • 1 < = s t a r t P o s , e n d P o s , k < = 1000 1 <= startPos, endPos, k <= 1000 1<=startPos,endPos,k<=1000

解法:组合数学

我们定义 startPos ----> endPos为正方向,endPos----> startPos为负方向。

我们假设往 正方向 走了 a步,那么往 负方向 就走了剩下的步数,即 k - a步。

如果成立,必须满足 a − ( k − a ) = d a - (k - a) = d a(ka)=d d = a b s ( s t a r t P o s − e n d P o s ) d = abs(startPos - endPos) d=abs(startPosendPos)

所以我们最后的答案为 C k a C_{k}^{a} Cka,即 C k k + d 2 C_{k}^{\frac{k+d}{2}} Ck2k+d。所以 k + d k + d k+d 必须是偶数才行,否则不符合要求。

对于组合数,我们利用递推式 C m n = C m − 1 n + C m − 1 n − 1 C_m^n = C_{m-1}^n + C_{m-1}^{n-1} Cmn=Cm1n+Cm1n1,求出 C k k C_k^k Ckk

最终返回 C k a C_k^a Cka即可。

时间复杂度: O ( k 2 ) O(k ^ 2) O(k2)

C++代码:

const int MOD = 1e9 + 7;
using LL = long long;

class Solution {
public:
    int numberOfWays(int startPos, int endPos, int k) {
        int d = abs(startPos - endPos);
        if(d > k || (k + d) % 2 == 1) return 0;

        LL c[k+1][k+1];
        memset(c,0,sizeof c);
        for(int i = 0;i <= k;i++){
            c[i][0] = 1;
            for(int j = 1;j <= i;j++) c[i][j] = (c[i-1][j] + c[i-1][j-1]) % MOD;
        }

        return c[k][(k + d) / 2];
    }    
};