You are given two positive integers startPos
and endPos
. Initially, you are standing at position startPos
on an infinite number line. With one step, you can move either one position to the left, or one position to the right.
Given a positive integer k
, return the number of different ways to reach the position endPos
starting from startPos
, such that you perform exactly k
steps. Since the answer may be very large, return it modulo 109 + 7
.
Two ways are considered different if the order of the steps made is not exactly the same.
Note that the number line includes negative integers.
Example 1:
Input: startPos = 1, endPos = 2, k = 3 Output: 3 Explanation: We can reach position 2 from 1 in exactly 3 steps in three ways: - 1 -> 2 -> 3 -> 2. - 1 -> 2 -> 1 -> 2. - 1 -> 0 -> 1 -> 2. It can be proven that no other way is possible, so we return 3.
Example 2:
Input: startPos = 2, endPos = 5, k = 10 Output: 0 Explanation: It is impossible to reach position 5 from position 2 in exactly 10 steps.
Constraints:
1 <= startPos, endPos, k <= 1000
题目链接:https://leetcode.com/problems/number-of-ways-to-reach-a-position-after-exactly-k-steps/
题目大意:直线给两点,从起点到终点走k步的方案数
题目分析:最容易想到的是记忆化搜索,dp[i][j]表示从位置i到终点走k步的方案数
dp[i][j] = dp[abs(i - 1)][j - 1] + dp[i + 1][j - 1]
94ms,时间击败82.98%
class Solution {
int[][] dp = new int[1001][1001];
final int mod = 1000000007;
int dfs(int d, int k) {
if (d > k) {
return 0;
}
if (d == k) {
return 1;
}
if (dp[d][k] != 0) {
return dp[d][k];
}
int ans = (dfs(Math.abs(d - 1), k - 1) + dfs(d + 1, k - 1)) % mod;
dp[d][k] = ans;
return ans;
}
public int numberOfWays(int startPos, int endPos, int k) {
int d = Math.abs(endPos - startPos);
if (d % 2 != k % 2 || d > k) {
return 0;
}
return dfs(d, k);
}
}
组合数方法:
设向右走x步,向左走y步,假设endPos比startPos大则
x - y = endPos - startPos
x + y = k
联立得x = (endPos - startPos + k) / 2,答案即为C(n, x),取模需要用到除法逆元,由费马小定理a^(p - 1) ≡ 1 mod p
a * a^(p - 2) ≡ 1 mod p
b * a^(p - 2) ≡ b / a mod p
C(n, x) = n * (n - 1) * ... * (n - i + 1) / x! (0 < i <= x)
2ms,时间击败98.14%
class Solution {
// x + y = k
// y - x = s - e
// x = (k + s - e) / 2
final int mod = 1000000007;
int qpow(long x, int n) {
long ans = 1;
while (n != 0) {
if ((n & 1) == 1) {
ans = (ans * x) % mod;
}
n >>= 1;
x = (x * x) % mod;
}
return (int)ans;
}
int C(int n, int k) {
if (n - k < k) {
k = n - k;
}
long ans = 1;
for (int i = 1; i <= k; i++) {
long b = (long)((n - i + 1) % mod);
long a = (long)(i % mod);
ans = ans * (b * qpow(a, mod - 2) % mod) % mod;
}
return (int)ans;
}
public int numberOfWays(int startPos, int endPos, int k) {
int d = Math.abs(endPos - startPos);
if (d % 2 != k % 2 || d > k) {
return 0;
}
int l = (k + d) >> 1;
return C(k, l);
}
}