题目链接:5274. 停在原地的方案数

You have a pointer at index 0 in an array of size arrLen. At each step, you can move 1 position to the left, 1 position to the right in the array or stay in the same place (The pointer should not be placed outside the array at any time).

Given two integers steps and arrLen, return the number of ways such that your pointer still at index 0 after exactly steps steps.

Since the answer may be too large, return it modulo \(10^9 + 7\).

Example 1:

Input: steps = 3, arrLen = 2
Output: 4
Explanation: There are 4 differents ways to stay at index 0 after 3 steps.
Right, Left, Stay
Stay, Right, Left
Right, Stay, Left
Stay, Stay, Stay

Example 2:

Input: steps = 2, arrLen = 4
Output: 2
Explanation: There are 2 differents ways to stay at index 0 after 2 steps
Right, Left
Stay, Stay

Example 3:

Input: steps = 4, arrLen = 2
Output: 8

Constraints:

  • 1 <= steps <= 500
  • 1 <= arrLen <= 10^6

题解

要想在第 n 步到达 0 点,那么第 n-1 步必须在 0 点或者 1 点,

要想第 n-1 步在 0 点,那么第 n-2 步必须在 0 点或者 1 点。

要想第 n-1 步在 1 点,那么第 n-2 步必须在 0 点,1 点,2 点。

...

...

由此看出这是动态规划的问题。

定义 int 型二维数组 dp[501][252],dp[i][j] 表示第 i 步到达 j 点的方案数。

因为 steps 最大为 500,下标从 0 开始,所以大小为 501,

因为 500 步之内想要回到 0 点,向右走最多 250 步,通过上面的步骤中第三行所示,需要向右多出一位,用来计算后面的值,所以要加 1,又因为下标从 0 开始,所以加 2。故大小为 252。

公式如下:$$dp[i][j]=\begin{cases}1&\text{}i=j=0\dp[i-1][j]+dp[i-1][j+1]&\text{}i>0且j=0\dp[i-1][j-1]+dp[i-1][j]+dp[i-1][j+1]&\text{}i>0且j>0\end{cases}$$

Example 1 计算步骤如下:

时间复杂度:\(O(m*min(\frac{m}{2}, n))\),m 表示 steps,n 表示 arrLen。

空间复杂度:\(O(1)\),因为大小固定,与 steps,arrLen 无关。

Java代码(第6次提交)

我发现最里面的判断执行的次数太多,而且好像可以提出来。

// 执行时间:7ms
class Solution {
public int numWays(int steps, int arrLen) {
int mod = 1000000007;
int[][] dp = new int[501][252];
dp[0][0] = 1;
int right = 0;
for (int i = 1; i <= steps; ++i) {
right = Math.min(Math.min(i, steps - i), arrLen - 1);
// 第0列只能加正上方和右上方,左上方出界了
dp[i][0] = (dp[i - 1][0] + dp[i - 1][1]) % mod;
for (int j = 1; j <= right; ++j) {// 从1开始
// 左上方和正上方
dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j]) % mod;
dp[i][j] = (dp[i][j] + dp[i - 1][j + 1]) % mod;// 右上方
}
}
return dp[steps][0];
}
}

Java代码(第5次提交)

// 执行时间:9ms
class Solution {
public int numWays(int steps, int arrLen) {
int mod = 1000000007;
int[][] dp = new int[501][252];
dp[0][0] = 1;
int right = 0;
for (int i = 1; i <= steps; ++i) {
// 将这里直接用一行表示
right = Math.min(Math.min(i, steps - i), arrLen - 1);
for (int j = 0; j <= right; ++j) {
dp[i][j] = (dp[i][j] + dp[i - 1][j]) % mod;// 两行合为一行
if (j > 0) {
// 两行合为一行
dp[i][j] = (dp[i][j] + dp[i - 1][j - 1]) % mod;
}
// 两行合为一行
dp[i][j] = (dp[i][j] + dp[i - 1][j + 1]) % mod;
}
}
return dp[steps][0];
}
}

Java代码(第4次提交)

// 执行时间:11ms
class Solution {
public int numWays(int steps, int arrLen) {
int mod = 1000000007;
// 第3次太啰嗦,直接固定为最大范围更节省时间,快6ms,
// 这说明计算比申请内存(这里申请的空间也不大)更耗时
int[][] dp = new int[501][252];
dp[0][0] = 1;
int right = 0;
for (int i = 1; i <= steps; ++i) {
right = Math.min(i, steps - i);
right = Math.min(right, arrLen - 1);
for (int j = 0; j <= right; ++j) {
dp[i][j] += dp[i - 1][j];
dp[i][j] %= mod;
if (j > 0) {
dp[i][j] += dp[i - 1][j - 1];
dp[i][j] %= mod;
}
dp[i][j] += dp[i - 1][j + 1];
dp[i][j] %= mod;
}
}
return dp[steps][0];
}
}

Java代码(第3次提交)

其实步数最多为 500 步,所以最多向右走 250 步,如果继续向右走 1 步,那么就无法回到原点。所以 steps >> 1,又因为需要计算 dp[i][steps >> 1],所以右边还需要 1 位,因此要加 1,又因为这是下标(从 0 开始),所以最终是 (steps >> 1) + 2,但是又不能超过限定的范围。所以就变成了下面写的那样。

// 执行用时:17ms
class Solution {
public int numWays(int steps, int arrLen) {
int mod = 1000000007;
// 如此啰嗦
int[][] dp = new int[steps + 1][Math.min((steps >> 1) + 2, arrLen + 1)];
dp[0][0] = 1;
int right = 0;
for (int i = 1; i <= steps; ++i) {
right = Math.min(i, steps - i);
right = Math.min(right, arrLen - 1);
for (int j = 0; j <= right; ++j) {
dp[i][j] += dp[i - 1][j];
dp[i][j] %= mod;
if (j > 0) {
dp[i][j] += dp[i - 1][j - 1];
dp[i][j] %= mod;
}
dp[i][j] += dp[i - 1][j + 1];
dp[i][j] %= mod;
}
}
return dp[steps][0];
}
}

Java代码(第2次提交)

第1次提交的时候忘记将输出删掉,,,结果超时了。

第2次提交,内存超出限制。原因是 arrLen 达到 \(10^6\),导致数组过大。

class Solution {
public int numWays(int steps, int arrLen) {
int mod = 1000000007;
int[][] dp = new int[steps + 1][arrLen + 1];// 这里超出内存限制
dp[0][0] = 1;
int right = 0;
for (int i = 1; i <= steps; ++i) {
right = Math.min(i, steps - i);
right = Math.min(right, arrLen - 1);
for (int j = 0; j <= right; ++j) {
dp[i][j] += dp[i - 1][j];
dp[i][j] %= mod;
if (j > 0) {
dp[i][j] += dp[i - 1][j - 1];
dp[i][j] %= mod;
}
dp[i][j] += dp[i - 1][j + 1];
dp[i][j] %= mod;
}
}
return dp[steps][0];
}
// private void print(int[][] dp) {
// for (int i = 0; i < dp.length; ++i) {
// for (int j = 0; j < dp[i].length; ++j) {
// System.out.print(dp[i][j] + " ");
// }
// System.out.println();
// }
// System.out.println();
// }
}

原文链接https://www.cnblogs.com/wowpH/p/11924796.html

- End - wowpH - cnblogs -

LeetCode 5274. Number of Ways to Stay in the Same Place After Some Steps - Java - DP的更多相关文章

  1. 【leetcode】1269. Number of Ways to Stay in the Same Place After Some Steps

    题目如下: You have a pointer at index 0 in an array of size arrLen. At each step, you can move 1 positio ...

  2. leetcode面试准备:Decode Ways

    1 题目 A message containing letters from A-Z is being encoded to numbers using the following mapping: ...

  3. 【一天一道LeetCode】#91. Decode Ways

    一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 A messa ...

  4. 【LeetCode】91. Decode Ways 解题报告(Python)

    [LeetCode]91. Decode Ways 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fux ...

  5. cf466C Number of Ways

    C. Number of Ways time limit per test 2 seconds memory limit per test 256 megabytes input standard i ...

  6. 【LeetCode】91. Decode Ways

    题目: A message containing letters from A-Z is being encoded to numbers using the following mapping: ' ...

  7. C#版 - Leetcode 191. Number of 1 Bits-题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - L ...

  8. [leetcode]200. Number of Islands岛屿个数

    Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surro ...

  9. [leetcode]694. Number of Distinct Islands你究竟有几个异小岛?

    Given a non-empty 2D array grid of 0's and 1's, an island is a group of 1's (representing land) conn ...

随机推荐

  1. 关于STM32 Flash的一些问题

    注:本人感觉是STM32 Flash本身的问题. 最近做STM32的远程升级,保存到Flash里面,用于记录更新状态的信息总是无故的清理掉 最终测试发现 STM32的 Flash 擦除操作 并不一定会 ...

  2. 第09组 Alpha冲刺(3/6)

    队名:观光队 组长博客 作业博客 组员实践情况 王耀鑫 过去两天完成了哪些任务 文字/口头描述 完成服务器连接数据库部分代码 展示GitHub当日代码/文档签入记录 接下来的计划 服务器网络请求,vu ...

  3. Dice Similarity Coefficent vs. IoU Dice系数和IoU

    Dice Similarity Coefficent vs. IoU Several readers emailed regarding the segmentation performance of ...

  4. [BUAA 软工]提问回顾与个人总结

    项目 内容 这个作业属于哪个课程 北航软工 这个作业的要求在哪里 提问回顾与个人总结 我在这个课程的目标是 学习如何以团队的形式开发软件,提升个人软件开发能力 这个作业在哪个具体方面帮助我实现目标 督 ...

  5. 权重轮询调度算法(WeightedRound-RobinScheduling)

    权重轮询调度算法(WeightedRound-RobinScheduling)-Java实现 ----参考Nginx中负载均衡算法实现 这里主要参考这篇文章的实现: Nginx 负载均衡-加权轮询策略 ...

  6. Android -------- kotlin插件神器Json直接生成javaBean

    这是一个data class从JSON字符串生成Kotlin 的插件,换句话说,是一个将JSON字符串转换为Kotlin data class(Json到Kotlin)的插件 在使用Kotlin进行开 ...

  7. 【转】模糊测试(fuzzing)是什么

    一.说明 大学时两个涉及“模糊”的概念自己感觉很模糊.一个是学数据库出现的“模糊查询”,后来逐渐明白是指sql的like语句:另一个是学专业课时出现的“模糊测试”. 概念是懂的,不外乎是“模糊测试是一 ...

  8. 由crt和key文件生成keystore文件

    该图转自知乎 海棠依旧 1.先生成p12文件,生成的时候需要指定密码 openssl pkcs12 -export -in your_crt.crt -inkey your_key.key -out ...

  9. EasyNVR网页摄像机无插件H5、谷歌Chrome直播方案之使用RTSP流判断摄像机设备是否在线以及快照抓取

    背景分析 熟知EasyNVR产品的小伙伴都知道,通过纯Web化的交互方式,只要配置出摄像机的IP.端口.用户名.密码等信息,就可以将地址进行通道配置完成,即可将设备接入.如果设备支持Onvif协议,E ...

  10. qt model/view/delegate

    Qt Model/View理解(一)---构造model https://blog.csdn.net/weixin_42303052/article/details/89233887 Qt Model ...