1269. 停在原地的方案数

本文解析了一道LeetCode题目,采用动态规划算法求解在给定步数内到达数组特定位置的方法数量。通过逐步优化,从初步实现到最后精简版,显著提升了执行效率。

题目链接:leetcode.

还以为是回溯,看了提示说是动态规划,那我就瞎写写吧

28 / 31 个通过测试用例
超时

class Solution {
public:
    int numWays(int steps, int arrLen) {
        vector<vector<int>> dp(steps, vector<int>(arrLen, 0));
        dp[0][0] = 1;
        dp[0][1] = 1;
        for(int i = 1;i < steps;++i)
        {
        	for(int j = min(i + 1, arrLen - 1);j >= 0;--j)
        	{
        		dp[i][j] += dp[i - 1][j] % 1000000007;
                dp[i][j] %= 1000000007;
        		if(j > 0)
        		{
        			dp[i][j] += dp[i - 1][j - 1] % 1000000007;
                    dp[i][j] %= 1000000007;
        		}
        		if(j < arrLen - 1)
        		{
        			dp[i][j] += dp[i - 1][j + 1] % 1000000007;
                    dp[i][j] %= 1000000007;
        		}
        	}
        }
        return dp[steps - 1][0];
    }
};

官解优化了一下动规矩阵的宽度

/*
执行用时:76 ms, 在所有 C++ 提交中击败了20.34%的用户
内存消耗:12.7 MB, 在所有 C++ 提交中击败了42.37%的用户
*/ 
class Solution {
	const int M = 1000000007; 
public:
    int numWays(int steps, int arrLen) {
        //最多跳到steps的位置
        int len = min(steps, arrLen);
        vector<vector<int>> dp(steps, vector<int>(len, 0));
        dp[0][0] = 1;
        dp[0][1] = 1;
        for(int i = 1;i < steps;++i)
        {
        	for(int j = 0;j < len;++j)
        	{
        		dp[i][j] += dp[i - 1][j];
        		if(j > 0)
        		{
        			dp[i][j] = (dp[i - 1][j - 1] + dp[i][j]) % M;
        		}
        		if(j < len - 1)
        		{
        			dp[i][j] = (dp[i - 1][j + 1] + dp[i][j]) % M;
        		}
        	}
        }
        return dp[steps - 1][0];
    }
};

评论里说还能再优化一下,宽度最长为steps/2,因为要过去再回来

/*
执行用时:36 ms, 在所有 C++ 提交中击败了48.30%的用户
内存消耗:9.8 MB, 在所有 C++ 提交中击败了55.93%的用户
*/ 
class Solution {
	const int M = 1000000007; 
public:
    int numWays(int steps, int arrLen) {
        //最多跳到steps的位置
        int len = min(steps / 2 + 1, arrLen);
        vector<vector<int>> dp(steps, vector<int>(len, 0));
        dp[0][0] = 1;
        dp[0][1] = 1;
        for(int i = 1;i < steps;++i)
        {
        	for(int j = 0;j < len;++j)
        	{
        		dp[i][j] += dp[i - 1][j];
        		if(j > 0)
        		{
        			dp[i][j] = (dp[i - 1][j - 1] + dp[i][j]) % M;
        		}
        		if(j < len - 1)
        		{
        			dp[i][j] = (dp[i - 1][j + 1] + dp[i][j]) % M;
        		}
        	}
        }
        return dp[steps - 1][0];
    }
};
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值