《LeetCode之每日一题》:30.停在原地的方案数
Posted 是七喜呀!
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《LeetCode之每日一题》:30.停在原地的方案数相关的知识,希望对你有一定的参考价值。
题目链接: 停在原地的方案数
有关题目
有一个长度为 arrLen 的数组,开始有一个指针在索引 0 处。
每一步操作中,你可以将指针向左或向右移动 1 步,
或者停在原地(指针不能被移动到数组范围外)。
给你两个整数 steps 和 arrLen ,请你计算并返回:
在恰好执行 steps 次操作以后,指针仍然指向索引 0 处的方案数。
由于答案可能会很大,请返回方案数 模 10^9 + 7 后的结果。
示例 1:
输入:steps = 3, arrLen = 2
输出:4
解释:3 步后,总共有 4 种不同的方法可以停在索引 0 处。
向右,向左,不动
不动,向右,向左
向右,不动,向左
不动,不动,不动
示例 2:
输入:steps = 2, arrLen = 4
输出:2
解释:2 步后,总共有 2 种不同的方法可以停在索引 0 处。
向右,向左
不动,不动
示例 3:
输入:steps = 4, arrLen = 2
输出:8
提示:
1 <= steps <= 500
1 <= arrLen <= 10^6
题解
1、动态规划
思路:
1.定义数组含义:
用dp[i][j]表示在 i 步操作之后,指针位于下标 j 的方案数。其中,i 的取值范围[0,steps],j的取值范围[0,arrLen - 1]
2.找出状态转移方程
由于每走一步操作后,指针指针有三种移动方式,向左,向右,或者不动,所以
dp[i][j] = dp[i - 1][j - 1] + dp[i-1][j] + dp[i - 1][j + 1]
3.找出初始值
未进行任何操作时,指针一定停留在原位,故dp[0][0] = 1;
class Solution {
public:
const int MODULO = 1000000007;
int numWays(int steps, int arrLen) {
int MaxCol = min(steps,arrLen - 1);
vector<vector<int>> dp(steps + 1,vector<int>(MaxCol + 1));
dp[0][0] = 1;
for (int i = 1; i <= steps; i++)//移动步数
{
for (int j = 0; j <= MaxCol; j++)//所位于下标
{
dp[i][j] = dp[i - 1][j];
if (j - 1 >= 0)//控制左边界
dp[i][j] = (dp[i][j] + dp[i - 1][j - 1]) % MODULO;
if (j <= MaxCol - 1)//控制右边界
dp[i][j] = (dp[i][j] + dp[i - 1][j + 1]) % MODULO;
}
}
return dp[steps][0];
}
};
时间复杂度:O(steps * min(steps,arrLen - 1))
空间复杂度:O(steps * min(steps,arrLen - 1))
2、优化动态规划
结合题目,根据数学知识,移动几步后,要想归0,移动步数i必须<=steps / 2
3、滚动数组
注意点
class Solution {
public:
const int MODULO = 1000000007;
int numWays(int steps, int arrLen) {
int MaxCol = min(steps / 2,arrLen - 1);
//我们对着边进行了上面2中所提到的优化
vector<int> dp(MaxCol + 1);
dp[0]= 1;
for (int i = 1; i <= steps; i++)
{
vector<int> dpNext(MaxCol + 1);
for (int j = 0; j <= MaxCol; j++)
{
dpNext[j] = dp[j];//对应原二维数组中的dp[i - 1][j]
if (j - 1 >= 0)
dpNext[j] = (dpNext[j] + dp[j - 1]) % MODULO;//这个dp[j] 对应原数组中的dp[i][j]
if (j <= MaxCol - 1)
dpNext[j] = (dpNext[j] + dp[j + 1]) % MODULO;
}
dp = dpNext;
}
return dp[0];
}
};
时间复杂度:O(steps * min(steps / 2,arrLen - 1))
空间复杂度:O(min(steps / 2,arrLen - 1))
以上是关于《LeetCode之每日一题》:30.停在原地的方案数的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode1269. 停在原地的方案数 / 剑指 Offer 38. 字符串的排列 / 216. 组合总和 III / 剑指 Offer 39. 数组中出现次数超过一半的数字/229. 求众数(