动态规划之打家劫舍

Posted IT海洋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态规划之打家劫舍相关的知识,希望对你有一定的参考价值。

动态规划(一)之打家劫舍

做过算法题的小伙伴应该都知道动态规划吧,它无论是在ACM比赛还是在各大公司面试中都占有非常高的比重,可想而知动态规划在算法题中的地位。坏蛋哥在一开始就可以告诉小伙伴们,动态规划的题难的话可以非常难,简单的也可以so easy 的做出来,所以我分享的一般都是经典的题目,能把经典的吃透,再去挑战难度更大的肯定事半功倍。


今天分享的两个主角是打家劫舍(一)和打家劫舍(二)。爱问问题的小伙伴就要问了:那有没有打家劫舍(三)呢.......哈哈,那肯定是有的啦,不然怎么对得起坏蛋哥这讲解的智商呢(低调!)



动态规划的核心思想


说到动态规划,就不得不提一下递归了,坏蛋哥认为动态规划就是对递归的一种时间复杂度的优化,学过基本的算法的小伙伴肯定知道,要换取时间复杂度,那么很大可能就是要牺牲空间复杂度。是的,你没有听错。它的本质也就是用空间来换取时间。


动态规划重要的几个点:

1️⃣ 子问题(lamp sub-problem),也就是如何把一个复杂的问题分解。这儿也就引出了动态规划的重头戏--转移方程,后面我会讲解什么是转移方程


2️⃣ 数组,在动态规划的算法中,一般是用数组来作为辅助存储。所以我们要选择一个合适的辅助数组(比如是一维还是二维,数组的长度等等)


3️⃣ 计算顺序,举个简单的栗子:大家都应该知道斐波那契数列(Fibonacci sequence)吧,它是这样一个数列:0、1、1、2、3、5、8、13、21、34、……。是不是有这样的规律 f(i)=f(i-1)+f(i-2),i是数组的下标。试想如果我们先计算f(6),那么就要递归等待f(5)和f(4),然而f(5)又要递归f(4)和f(3)。是不是f(4)需要被递归多次。如果在f(i)非常大的时候,那么时间复杂度就会非常的高。但是我按照f(1),f(2),f(3)的顺序依次计算,结果又会怎样呢?很显然嘛,时间复杂度变为了O(n)。可想而知计算顺序的重要性。


4️⃣ 初始化,在后面的例子中坏蛋哥会解释这个过程。


有了上面的知识储备,那么就让我们实际来解题试试(疗效好不好,事实说了算)


打家劫舍一


这道题是leetcode上面比较经典的动态规划题,获取原题(https://leetcode-cn.com/problems/house-robber/


动态规划(一)之打家劫舍


在解动态规划算法的时候,某些题正好是选与不选的概念


具体解释是这样的,我们换一种思路:我们要得到最大值,是不是就涉及到一个“选与不选”的概念,比如说上面有四个元素,我们依次标为a[0],a[1],a[2],a[3]。是不是我选了a[3],就不能选a[2]了,就只能选a[1]和a[1]之前的元素呢?


本题的题解思路:


1️⃣ 找出转移方程(又一个大的状态转移到一个小的状态):dp[i]=max( f(i) + dp[i-2] ,dp[i-1] )    

注:解释一下参数:dp[i] 表示0~i的数组偷取的最大money,f(i)便是第i个元素可以偷取的money。


2️⃣ 计算方向:很显然这个问题类似于斐波拉契数列,如果从后往前,那么是需要递归的,如果从前往后,那么就是一条路算到底。复杂度就变为了O(n)。


3️⃣  初始化:既然是从前往后,但是第一个元素的前两个元素怎么表示呢? 其实做法很简单,将数据前面加两个值为0的元素不就解决问题了吗。


流程拉通下来,小伙伴们是不是感觉原来都是套路啊!


动态规划(一)之打家劫舍


是的,但是也有不按套路出牌的,但是是少数哦,那些能难到你怀疑人生。


最后我们就看一下具体的代码:

import static java.lang.Math.max;
class Solution {
public int rob(int[] nums) {
       //特判
       if (nums==null && nums.length==0){
           return 0;
      }
       
       //初始化变量
       int[] maxMoney=new int[nums.length+2];
       
       //开始计算
       for (int i=0;i<nums.length;i++){
           //maxMoney的i+2与nums相对应
           maxMoney[i+2]=max(maxMoney[i]+nums[i],maxMoney[i+1]);
      }
       
       return maxMoney[maxMoney.length-1];
  }
}


get到了吗,是不是感觉坏蛋哥的讲解这么的到位。是不是有想

以上是关于动态规划之打家劫舍的主要内容,如果未能解决你的问题,请参考以下文章

LeetCodeLeetCode之删除并获得点数——动态规划排序+动态规划

LeetCodeLeetCode之跳跃游戏——动态规划+贪心算法

Leetcode之动态规划(DP)专题-198. 打家劫舍(House Robber)

动态规划之周某打家劫舍问题

LeetCodeLeetCode之打家劫舍Ⅱ——暴力递归+动态规划解决循环问题+DP空间优化

经典动态规划:打家劫舍系列问题