LeetCode刷题日记2021-5-13/1269. 停在原地的方案数/动态规划

仅供自己学习记录

LeetCode刷题日记2021-5-13

题目描述

有一个长度为 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

题解思路

定义: dp[i][j]dp[i][j] 代表 step 为 i, arr 数组下标为 j 时, 方案的个数
状态转移方程: dp[i][j] = dp[i-1][j] + dp[i-1][j-1] + dp[i-1][j+1]dp[i][j]=dp[i−1][j]+dp[i−1][j−1]+dp[i−1][j+1]
到达 j 原地不动的话, dp[i][j] = dp[i-1][j]dp[i][j]=dp[i−1][j], 就是把 step = i-1 的方案数拿过来
到达 j 是从 j-1, 从 j 左边过来的, 移动一位可以到达 j, 所以把 dp[i-1][j-1]dp[i−1][j−1] 的方案数加上
到达 j 是从 j+1, 从 j 右边过来的, 移动一位可以到达 j, 所以把 dp[i-1][j+1]dp[i−1][j+1] 的方案数加上
题目允许不移动或者左右移动一位, 所以可以把以上的结果都加起来
边界条件处理
dp 数组的下标和数组第几位之间很容易搞混, 在这题里面, steps 那一维度是从 1 开始计算, 而 arrLen 从0开始计算
🌰 针对 steps 从 1 开始计算举个例子:

steps = 4
steps: [0, 1, 2, 3, 4]
index: 0 1 2 3 4
创建数组的长度要用: dp_len = steps + 1 = 5
获取dp的最后一个值用 dp[steps] = dp[4] 拿到最后的那个数字

arrLen 那个维度, 注意 j-1 , j+1 不要超过数组边界
python 数组创建踩坑
最初创建二维数组的时候使用

dp = [[0] * 3] * (4 + 1)
发现答案有问题, 我只要改变其中一个值 dp[2][2], 其他行也会跟着改变. 后来debug一下发现这种创建二维数组的方式其实他们的一维数组的地址都是一样的, 感兴趣的同学可以自己试试.

 dp = [[0] * 3] * (4 + 1)
 id(dp[0])
4505885120
id(dp[1])
4505885120

 b = [[0 for i in range(3)] for j in range(4+1)]
id(b[0])
4505886208
 id(b[1])
4505908736

其他整理
为什么怕数据溢出要用 10^9+7 取模?
https://blog.csdn.net/mandagod/article/details/79767954
取模的特点: (a + b) % m = a%m + b%m
dp过程中二维数组 j 循环那部分不需要全部都计算
因为当step < arrLen, 要想回到 0 , 至少是走一半路step/2就要折回来了. 否则到达不了原点了.

题解代码

    mod=10**9+7
    maxlen=min(steps//2+1,arrLen)
    dp=[[0 for _ in range(maxlen)]for _ in range(steps+1)]

    dp[0][0]=1

    for step in range(1,steps+1):
        for j in range(maxlen):
            dp[step][j]=dp[step-1][j]%mod
            if j-1>=0:
                dp[step][j]=(dp[step][j]+dp[step-1][j-1])%mod
            if j+1<maxlen:
                dp[step][j]=(dp[step][j]+dp[step-1][j+1])%mod
    return dp[steps][0]

来源

https://leetcode-cn.com/problems/number-of-ways-to-stay-in-the-same-place-after-some-steps/solution/chi-xiao-dou-yi-ge-jian-dan-de-jie-da-by-1smq/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值