Leetcode198. 打家劫舍(经典动态规划+优化)
Posted !0 !
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode198. 打家劫舍(经典动态规划+优化)相关的知识,希望对你有一定的参考价值。
题目链接:https://leetcode-cn.com/problems/house-robber/
解题思路
这是一道非常经典的动态规划问题。动态规划的题一般都是找到边界条件和状态转移方程。我们先来找一下规律,如果只有一家,则直接选择这一家。如果有两家,则选择其中金额大的一家。接下来就是关键了,如果有i(i > 2)
家,如果选择第i家,那么只能选择第i-2
家之前的最高总金额,否则选择不偷第i家,那么只能选择第i-1家之前的最高总金额。
所以我们用dp[i]
表示前i家能偷的最高总金额,状态转移方程就是:
d p [ i ] = { n u m s [ 0 ] (i=0) m a x ( n u m s [ 0 ] , n u m s [ 1 ] ) (i=1) m a x ( d p [ i − 2 ] + n u m s [ i ] , d p [ i − 1 ] ) (i > 1) dp[i] = \\left\\{ \\begin{aligned} & nums[0] & \\text{(i=0)} \\\\ & max(nums[0], nums[1]) & \\text{(i=1)}\\\\ & max(dp[i - 2] + nums[i], dp[i - 1]) & \\text{(i > 1)} \\end{aligned} \\right. dp[i]=⎩⎪⎨⎪⎧nums[0]max(nums[0],nums[1])max(dp[i−2]+nums[i],dp[i−1])(i=0)(i=1)(i > 1)
代码
class Solution {
public int rob(int[] nums) {
int n = nums.length;
if(n == 1) //特判
return nums[0];
int[] dp = new int[n];
dp[0] = nums[0]; //只有一家时
dp[1] = Math.max(nums[0], nums[1]); //有两家时
for(int i = 2; i < n; i++) //找出前i家能投的最高总金额
dp[i] = Math.max(nums[i] + dp[i - 2], dp[i - 1]);
return dp[n - 1];
}
}
复杂度分析
- 时间复杂度:O(n)
- 空间复杂度:O(n)
优化
我们可以发现,dp[i]之和dp[i - 1] 和 dp[i - 2]有关,所以我们可以用两个变量记录前面两个状态,从而对空间进行优化。
代码
class Solution {
public int rob(int[] nums) {
int n = nums.length;
if (n == 1)
return nums[0];
int f = nums[0], s = Math.max(nums[0], nums[1]);
for (int i = 2; i < n; i++) {
int t = s;
s = Math.max(f + nums[i], s);
f = t;
}
return s;
}
}
复杂度分析
- 时间复杂度:O(n)
- 空间复杂度:O(1)
以上是关于Leetcode198. 打家劫舍(经典动态规划+优化)的主要内容,如果未能解决你的问题,请参考以下文章