剑指 Offer II 089. 房屋偷盗(198. 打家劫舍)

题目:

 

思路:

【0】这道题吧,怎么说,算是大学了解动态规划入门的一道题吧。思路和跳台阶很像,因为当位置为N的时候,情况可以分为两种,就是N的位置选和不选,选的话,那么根据最大值的原理,必然是F(N)=  x + F(N-2) ,x为N位置的值。如果不选,那么必然是因为F(N-1)> x + F(N-2) ,所以基于最大值的理论,应该F(N)= F(N-1),故可以理解为 F(N) = Math.max(F(N-1), X + F(N-2)) , 这种可以直接是到第三个数开始,不然其实就只能从第一个数和第二个数中进行二选一。

【1】动态规划的方式

代码展示:

动态规划的方式:

//时间0 ms击败100%
//内存38.8 MB击败71.94%
//时间复杂度 O(n)
//空间复杂度 O(n)
class Solution {
    public int rob(int[] nums) {
        if (nums.length == 0)  return 0;

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

//优化空间复杂度
//时间0 ms击败100%
//内存38.9 MB击败51.34%
//时间复杂度 O(n)
//空间复杂度 O(1)
//先说说为什么能简化吧,首先要求的是最大值,所以也就是说,不同位置的最大数其实不重要
//其次这个的函数有点像是跳台阶那道题,所以计算当前N位置的值,需要的是知道N-1和N-2的最大值即可,那么基于这样就不用了创建数组了,直接用常量即可
class Solution {
    public int rob(int[] nums) {
        int prev = 0;
        int curr = 0;

        // 每次循环,计算“偷到当前房子为止的最大金额”
        for (int i : nums) {
            // 循环开始时,curr 表示 dp[k-1],prev 表示 dp[k-2]
            // dp[k] = max{ dp[k-1], dp[k-2] + i }
            int temp = Math.max(curr, prev + i);
            prev = curr;
            curr = temp;
            // 循环结束时,curr 表示 dp[k],prev 表示 dp[k-1]
        }

        return curr;
    }
}

 

//时间0 ms击败100%//内存38.8 MB击败71.94%//时间复杂度 O(n)//空间复杂度 O(n)class Solution {    public int rob(int[] nums) {        if (nums.length == 0)  return 0;
        int n = nums.length;        int[] dp = new int[n+1];        dp[0] = 0;        dp[1] = nums[0];        for (int k = 2; k <= n; k++) {            dp[k] = Math.max(dp[k-1], nums[k-1] + dp[k-2]);        }        return dp[n];    }}
//优化空间复杂度//时间0 ms击败100%//内存38.9 MB击败51.34%//时间复杂度 O(n)//空间复杂度 O(1)//先说说为什么能简化吧,首先要求的是最大值,所以也就是说,不同位置的最大数其实不重要//其次这个的函数有点像是跳台阶那道题,所以计算当前N位置的值,需要的是知道N-1和N-2的最大值即可,那么基于这样就不用了创建数组了,直接用常量即可class Solution {    public int rob(int[] nums) {        int prev = 0;        int curr = 0;
        // 每次循环,计算“偷到当前房子为止的最大金额”        for (int i : nums) {            // 循环开始时,curr 表示 dp[k-1],prev 表示 dp[k-2]            // dp[k] = max{ dp[k-1], dp[k-2] + i }            int temp = Math.max(curr, prev + i);            prev = curr;            curr = temp;            // 循环结束时,curr 表示 dp[k],prev 表示 dp[k-1]        }
        return curr;    }}
posted @ 2023-03-31 15:27  忧愁的chafry  阅读(19)  评论(0编辑  收藏  举报