vlambda博客
学习文章列表

算法-动态规划(二)

        今天继续我们的动态规划专题,集中练习一些有关动态规划的题,加深印象。

👉👀💬今日练习(一打家劫舍(LeetCode-198)。


        去偷沿街的房屋,且每个屋里都有数量不等的钱,用数组nums来表示所有屋里的金额。

        注意,如果偷相邻两个屋就会触发报警,计算在不触发报警的情况下,你一晚最多能偷到多少,返回最大值。如:

输入:[1,2,3,1]输出:4--------------输入:[2,7,9,3,1]输出:12=2+9+1

🙇思路:

        依旧是动态规划,还是我们之前强调的:

  1. 定义子问题,

  2. 找出状态转移,即子问题的递推关系

  3. 确定【填表】的计算顺序

  4. 空间优化,这前期可以先放一放,等熟练了在来考虑



一、定义子问题

        什么是子问题?子问题是和原问题相似,但规模较小的问题。求解从所有屋里可以盗取的最大金额,子问题就是,“从K个屋里能偷到的最大金额”。我们定义子问题参数为k,如果有n个房屋的话,就一共有n个子问题,动态规划就是要求这一堆子问题的解。

算法-动态规划(二)

动态规划要求有两个性质:

  1. 原问题可由子问题表示,否则求半天得不到原文那就很尴尬了。这道题中,n=k,就是原问题。

  2. 一个子问题也可以由其他子问题来得到。如这道题里,f(k)可以由f(k-1)和f(k-2)来得到,至于为什么我们放后面来讲。

        满足以上两个性质,一般就可以用动态规划来求解。

二、写出递推关系(状态转移)。


        这一步是动态规划的核心,也是难点,如果我们找不到递推关系,那么动态规划也没戏。

        我们来分析此题:

        假设有n个屋,屋里的金额分别是nums[0]、nums[1]、nums[2]···nums[n-1]、nums[n],第k个屋里的金额为nums[k-1],子问题f(k)表示从前k个屋能偷到的最大金额,偷前k个屋,有以下两种方案:

算法-动态规划(二)

  1. 偷第k个屋,那第k-1个屋就不能偷,否则会报警,所以

    f(k)=nums[k-1]+f(k-2)。

  2. 不偷第k个屋,所以我们可以偷前k-1个屋,所以f(k)=f(k-1)。

  3. 综上两步,偷前k个屋,最大金额为:
    f(k)=max(f(k-1) , nums[k-1]+f(k-2),也填上了上文中所说的f(k)由f(k-1)f(k-2)决定的坑。

  4. 在写递推关系的时候,要注意k=0时,f(0)=0;k=1时f(1)=nums[0]。

三、确定【填表】的计算顺序。


        一般情况下动态规划都是自低而上的的计算顺序。

代码:

public int rob(int[] nums){ int len=nums.length;    if(len <1){ return 0; } if(len<2){ return nums[0]; } int[] dp = new int[len+1]; dp[0]=0; dp[1]=nums[0]; for(int k=2;k<=len;k++){ dp[k]=Math.max(dp[k-1],nums[k-1]+dp[k-2]); } return dp[len];}

复杂度分析

  • 时间复杂度:O(N),需要到nums全部遍历一次。

  • 空间复杂度:O(N),我们需要用dp数组来保存所有的过程值


四、空间优化。

        在上面解法中我们需要一个len+1长的数组dp来保存所有的过程值,但核心代码:dp[k]=Math.max(dp[k-1],nums[k-1]+dp[k-2]);代码里我们只关系dp[k-1]和dp[k-2]这两个值,其他位置的值是啥,我们并不关心,也无需保存,所以这就是我们优化的点,我们可以仅用O(1)的空间就可以解决。

代码:

public int rob_1(int[] nums){ int len=nums.length;    if(len <1){ return 0; } if(len<2){ return nums[0];    } int prev=nums[0]; int curr=Math.max(prev,nums[1]); for(int k=2;k<len;k++){ int temp = curr; curr= Math.max(curr,nums[k]+prev); prev=temp; } return curr;}

复杂度分析

  • 时间复杂度:O(N),需要到nums全部遍历一次。

  • 空间复杂度:O(N),我们只保存了前两个房屋的最大金额



算法-动态规划(二)不积跬步,无以至千里。

文章有帮助的话,点个转发、在看呗算法-动态规划(二)

谢谢支持哟 (*^__^*)

END


算法-动态规划(二)👇