滚动数组-动态规划之-不同路径 II_20230421

文章介绍了滚动数组在动态规划中的应用,通过斐波那契数列和不同路径II问题举例,展示了如何通过滚动数组减少空间复杂度。一维数组可以通过转换为3个变量实现,二维数组可以简化为一维。滚动数组不仅限于动态规划,也可用于降低线性链表遍历的空间复杂度。

DP动态规划之-滚动数组

  1. 前言

在学习 不同路径II 的动态规划过程中,从介绍资料中了解到 滚动数组可以进一步降低动态规划解空间的复杂度,更高效利用计算机的储存空间。动态规划中的滚动数组究竟能发挥哪些作用,在常规的动态规划中,我们又是如何进行具体的应用呢?

从本质上理解,滚动数组的作用就是为了更好利用储存空间,用有限的空间不断进行覆盖,从而完成整体算法任务,具体而言分为两类:

  • 一维数组简化为2个或3个变量
  • 二维数组简化为1维数组
  1. 一维数组转化为滚动数组

具体看一个斐波那契数列的例子,中规中矩的动态规划数组一般设定为dp[n+1],其中n表示斐波那契数列的下标(位置),通过dp[n]=dp[n-1]+dp[n-2]求解出所有的斐波那契数列。

动态规划的基础解为dp[1]=1, dp[2]=1,然后通过循环求出每个位置上的斐波那契数字,最后返回dp[n]即为所求得的具体解。

int fib_normal_array(int n)
{
   
   
    int i;
    int dp[n+1];

    dp[1]=1;
    dp[2]=1;

    for(i=3;i<=n;i++)
    {
   
   
        dp[i]=dp[i-1]+dp[i-2];
    }

    return dp[n];
}

那么如何转化为滚动数组呢? 通过观察我们发现,对于每个位置上的斐波那契数字,它仅仅与前面两个相邻的斐波那契数字相关,再往前的斐波那契数字与它无关。这就给我们些微的思路,尝试探索用3个单独变量来滚动实现斐波那契数字的求解。假定f1,f2和f3为连续的三个斐波那契数字,f3=f1+f2, 接下来把f2赋值给f1, f3赋值给f2,神奇的事情就会发生,让我们看具体的代码实现。

int fib_scrolling_array(int n)
{
    int i;
    int f1;
    int f2;
    int f3;

    f1=1;
    f2=1;

    for(i=3;i<=n;i++)
    {
        f3=f1+f2;
        f1=f2;
        f2=f3;
    }

    return f3;
}

用图来进一步解释说明,可以观察出,f2和f3不断滚动到f1和f2, 周而复始,最终求得f3具体值,由于新值与旧值不断交换,形象称之为滚动。
在这里插入图片描述

上述例子可以看出,通过合理的变量设定,可以把占用空间从n降低为3个变量,但是工程问题永远都有两面性,减少了储存空间,那么如果要查找,就只能找到至多三个斐波那契数字,如果设定的一维数组,那么就可以通过下标任意查询。具体采用哪种模式,需要根据具体问题具体分析。

  1. 二维数组简化为一维数组

很多情况下,动态规划问题的求解有赖于DP二维数组,通过dp[i][j]与前面已知求得的解进行关联求和或求布尔运算,从而求出dp[i][j]的具体值。

看一个具体例子,前面曾经提到的 不同路径II的问题,常规情况下,利用二维DP数组进行求解,如果采用滚动数组的概念,则可以把二维数组优化为一维数组,如果进一步深入理解,也就是把二维数组的n×m个变量空间优化为m个变量空间,从形式上直观理解,二维数组自然退化为一维数组。

先给出 不同路径II的问题描述,问题引用自leetcode.

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish”)。现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?网格中的障碍物和空位置分别用 10 来表示。
在这里插入图片描述

这个问题可以称之为条件式的动态规划问题,这源于障碍物的限制,障碍物限制会导致递归模式中的剪枝情况出现,本问题采用DP迭代动态规划,它会通过判断语句,对不同的dp[i]][j]进行赋值。

动态规划的重要特征是通过最优化子问题定义状态转移方程,可以理解为先定义最优化子问题,然后通过定义的子问题递归或迭代求出原问题的解。

对于此问题,题目要求求解最终不同路径的数目,同时限制了路径的走向,对于任意一个坐标点f(i,j),如果需要求出到达此点的路径的总数目,可以分两种情况:

  • 情况1,如果此处存在路障,那么f(i,j)=0, 用编程语言描述,如果路障数组在某处obstacleGrid[i][j]的值为1,那么这个点和之前任何点都没有关系,到达此处的路径总数为0
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值