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/

posted @ 2021-05-14 13:06  TidalCoast  阅读(82)  评论(0编辑  收藏  举报