动态规划之打家劫舍
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)