动态规划——恰好移动K步到达某一位置的方法数目

恰好移动K步到达某一位置的方法数目

2400. 恰好移动 k 步到达某一位置的方法数目 - 力扣(LeetCode)

  • 给你两个 整数 startPosendPos 。最初,你站在 无限 数轴上位置 startPos 处。在一步移动中,你可以向左或者向右移动一个位置。

    • 给你一个正整数 k ,返回从 startPos 出发、恰好 移动 k 步并到达 endPos不同 方法数目。由于答案可能会很大,返回对 109 + 7 取余 的结果。
    • 如果所执行移动的顺序不完全相同,则认为两种方法不同。

    注意:数轴包含负整数。

    示例 1:

    输入:startPos = 1, endPos = 2, k = 3
    输出:3
    解释:存在 3 种从 1 到 2 且恰好移动 3 步的方法:
    - 1 -> 2 -> 3 -> 2.
    - 1 -> 2 -> 1 -> 2.
    - 1 -> 0 -> 1 -> 2.
    可以证明不存在其他方法,所以返回 3 。
    

    示例 2:

    输入:startPos = 2, endPos = 5, k = 10
    输出:0
    解释:不存在从 2 到 5 且恰好移动 10 步的方法。
    

    提示:

    • 1 <= startPos, endPos, k <= 1000
  • 先思考暴力搜索是否可以

    • 一个点只能往左或者往右行动,可以考虑递归求左边的方法数+右边的方法数
    • 递归的中止点,步数为0,若刚好到达,则这是一个方法返回1,否则返回0
class Solution {
public:
    int numberOfWays(int startPos, int endPos, int k) {
        return DFS(startPos,endPos,k);
    }

    int DFS(int startPos, int endPos, int k) {
        if(k == 0) {
            if(startPos == endPos){
                return 1;
            }
            return 0;
        }
        return DFS(startPos-1,endPos,k-1)+DFS(startPos+1,endPos,k-1);
    }
};
  • 暴力递归少数据证明正确,但是超时,考虑优化,即看看是否有重复计算的过程

  • IMG_2433(20230922-211051)

    • 存在重复计算过程,使用缓存记录 -> 记忆化搜索
    class Solution {
    public:
        vector<vector<int>> dp;
        const int MAX = pow(10,9)+7;
        int numberOfWays(int startPos, int endPos, int k) {
            //dp数组大小 dp[startpos][k]
            //考虑到 startpos-k 和startpos+k , 第一个大小为2k+1
            //第二个为k+1
            dp.resize(2*k + 1, vector<int>(k+1,-1));
            //调整startpos 至 0-2k
            return DFS(k,endPos-startPos+k,k);
        }
    
        int DFS(int startPos, int endPos, int k) {
            if(dp[startPos][k] != -1) return dp[startPos][k];
            if(k == 0) {
                if(startPos == endPos){
                    return 1;
                }
                return 0;
            }
            return dp[startPos][k] = (DFS(startPos-1,endPos,k-1)+DFS(startPos+1,endPos,k-1))%MAX;
        }
    };
    
  • 根据记忆化搜索的dp数组推导动态规划的状态转移方程

class Solution {
public:
    vector<vector<int>> dp;
    const int MAX = pow(10,9)+7;
    int numberOfWays(int startPos, int endPos, int k) {
        dp.resize(2*k + 1, vector<int>(k+1,-1));
        return DFS(k,endPos-startPos+k,k);
    }

    int DFS(int startPos, int endPos, int k) {
        if(dp[startPos][k] != -1) return dp[startPos][k];
        if(k == 0) {
            if(startPos == endPos){
                return 1;
            }
            return 0;
        }
        return dp[startPos][k] = (DFS(startPos-1,endPos,k-1)+DFS(startPos+1,endPos,k-1))%MAX;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值