leetcode算法题 pro1269 停在原地的方案数
leetcode算法题 pro1269 停在原地的方案数
原题地址:https://leetcode-cn.com/problems/number-of-ways-to-stay-in-the-same-place-after-some-steps/
题目描述
有一个长度为 arrLen 的数组,开始有一个指针在索引 0 处。
每一步操作中,你可以将指针向左或向右移动 1 步,或者停在原地(指针不能被移动到数组范围外)。
给你两个整数 steps 和 arrLen ,请你计算并返回:在恰好执行 steps 次操作以后,指针仍然指向索引 0 处的方案数。
由于答案可能会很大,请返回方案数 模 10^9 + 7 后的结果。
题目用例
输入:steps = 3, arrLen = 2 输出:4 解释:3 步后,总共有 4 种不同的方法可以停在索引 0 处。 向右,向左,不动 不动,向右,向左 向右,不动,向左 不动,不动,不动
输入:steps = 2, arrLen = 4 输出:2 解释:2 步后,总共有 2 种不同的方法可以停在索引 0 处。 向右,向左 不动,不动
输入:steps = 4, arrLen = 2
输出:8
题目思路
这道题是一道动态规划相关的题目,所以要用动态规划的思想来解决。首先我们从题干中可以得知,每一步操作可以向左、向右或停在原地不动,如果选择移动的话,不能超过数组的界限。那么,我们的首先要找出这道题的状态转移方程。设置一个二维数组dp[i][j]表示操作的状态,i表示当前的step数,j表示当前所在的下标,那么dp[i][j]就可以表示到达当前下标的方案数。每次操作,我们都可以有三种方式可以选择,分别是向左,向右,原地不动,所以当前状态的方案数可以看成上一步的方案数加上向右、向左和原地不动三种情况的步数,当然移动不能超过数组的下标范围。这样一来,就可以得出大致的状态转移方程了。转移方程为:dp[i][j] = dp[i-1][j-1] + dp[i-1][j] + dp[i-1][j+1]。有了状态转移方程后,还要确定数组的大小,i表示steps,所以1 <= i <= steps,j表示下标,所以 0 <= j <= arrlen-1,如果steps小于数组长度arrlen,那么下标最多只能到steps,所以j的实际范围是0 <= j <= min(steps,arrlen-1)。现在可以通过状态转移方程来写出程序了。
代码
1 class Solution { 2 public int numWays(int steps, int arrLen) { 3 int mod = 1000000007; 4 int maxColumn = Math.min(arrLen - 1, steps); 5 int dp[][] = new int[steps + 1][maxColumn + 1];//创建dp二维数组 6 dp[0][0] = 1; 7 dp[0][1] = 0; 8 for (int i = 1; i <= steps; i++) { 9 for (int j = 0; j <= maxColumn; j++) { 10 dp[i][j] = dp[i - 1][j];//当前步数等于上一情况不动的步数 11 if (j - 1 >= 0) { 12 //上一情况向左走没有回到原点 13 //加上上一情况左走的步数 14 dp[i][j] = (dp[i][j] + dp[i - 1][j - 1]) % mod; 15 } 16 if (j + 1 <= maxColumn) { 17 //上一情况下向右走没有越界的情况 18 //加上上一情况右走的步数 19 dp[i][j] = (dp[i][j] + dp[i - 1][j + 1]) % mod; 20 } 21 } 22 } 23 //for (int i = 0; i < steps; i++) { 24 // for (int j = 0; j < maxColumn; j++) { 25 // System.out.print(dp[i][j] + " "); 26 // } 27 //} 28 //System.out.println(); 29 return dp[steps][0];//返回终点是原点的方案数 30 } 31 }
官方更优解
由于每一步操作都只与上一次的操作有关,所以完全可以用一个一维的数组来解决,这样能够节省内存空间。
1 class Solution { 2 public int numWays(int steps, int arrLen) { 3 final int MODULO = 1000000007; 4 int maxColumn = Math.min(arrLen - 1, steps); 5 int[] dp = new int[maxColumn + 1]; 6 dp[0] = 1; 7 for (int i = 1; i <= steps; i++) { 8 int[] dpNext = new int[maxColumn + 1]; 9 for (int j = 0; j <= maxColumn; j++) { 10 dpNext[j] = dp[j]; 11 if (j - 1 >= 0) { 12 dpNext[j] = (dpNext[j] + dp[j - 1]) % MODULO; 13 } 14 if (j + 1 <= maxColumn) { 15 dpNext[j] = (dpNext[j] + dp[j + 1]) % MODULO; 16 } 17 } 18 dp = dpNext; 19 } 20 return dp[0]; 21 } 22 }
此题解来源于leetcode官方,网址:https://leetcode-cn.com/problems/number-of-ways-to-stay-in-the-same-place-after-some-steps/solution/ting-zai-yuan-di-de-fang-an-shu-by-leetcode-soluti/