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[i2]+nums[i],dp[i1])(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. 打家劫舍(经典动态规划+优化)的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode动态规划训练营(1~5天)

#动态规划 LeetCode 198 打家劫舍

LeetCode动态规划训练营(1~5天)

动态规划——leetcode198.打家劫舍

[LeetCode] 198. 打家劫舍II ☆☆☆(动态规划)

Leetcode No.198 打家劫舍(动态规划)