05 August 2008
在大小为 arrLen 的数组中的索引 0 处有一个指针。在每一步,可以在数组中向左移动 1 个位置,向右移动 1 个位置,或者留在原地(指针在任何时候都不应该放在数组之外)。
给定两个整数 step 和 arrLen,返回在精确 step 之后指针仍位于索引 0 的方式数。由于答案可能太大,因此以 109 + 7 为模返回。
Top Down DP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Solution {
int MOD = 1000000007;
int[][] dp;
public int numWays(int steps, int arrLen) {
dp = new int[steps+2][steps+1];
for(int[] arr : dp)
{
Arrays.fill(arr, -1);
}
dp[0][0] = 1;
return dfs(0, steps, arrLen);
}
public int dfs(int pos, int steps, int arrlen)
{
if(pos > steps)return 0;
if(dp[pos][steps]!=-1)return dp[pos][steps];
int res = 0;
res+=dfs(pos, steps-1, arrlen);
res%=MOD;
if(pos+1<arrlen)
{
res+=dfs(pos+1, steps-1, arrlen);
res%=MOD;
}
if(pos-1>=0)
{
res+=dfs(pos-1, steps-1, arrlen);
res%=MOD;
}
dp[pos][steps] = res;
return res;
}
}
Bottom Up
Initialize:
dpPrev[bound], dpNext[bound]
dpPrev[i] is a number of ways to reach position i calculated for the prev step
dpNext[i] is the same for the next step
Initially, dpPrev[0] = 1
Then repeat steps times:
calculate dpNext from dpPrev
dpNext[i] = (dpPrev[i] + dpPrev[i-1] + dpPrev[i+1]) % MOD
(when index is out of bounds, fall back to 0)
swap dpPrev and dpNext
Once done, return dpPrev[0]
TC: O(steps * min(arrLen, steps))
SC: O(min(arrLen, steps))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution {
private static final long MOD = 1_000_000_007;
public int numWays(int steps, int arrLen) {
int bound = Math.min(arrLen, steps / 2 + 1);
long[] dpPrev = new long[bound];
dpPrev[0] = 1;
long[] dpNext = new long[bound];
for (int step = 0; step < steps; step++) {
for (int i = 0; i < bound; i++) {
dpNext[i] = dpPrev[i];
if (i > 0)
dpNext[i] += dpPrev[i - 1];
if (i < bound - 1)
dpNext[i] += dpPrev[i + 1];
dpNext[i] %= MOD;
}
long[] tmp = dpPrev;
dpPrev = dpNext;
dpNext = tmp;
}
return (int) dpPrev[0];
}
}