小言_互联网的博客

LeetCode刷题笔记(House Robber)

371人阅读  评论(0)

最近xianggang有点不太平,作为一介平民只能衷心希望xianggang能尽快恢复平静,国家繁荣富强横扫一切敌对势力,正如毛主席曾说:“敌军围困万千重,我自岿然不动”。下面和大家分享一下刚刷的这道题吧!

题目如下:

题意分析:

给定一个表示每个房屋放有多少金钱的数组,在不触动报警系统的情况下(偷窃连着的两个房子即会触动报警系统),请问你最多能偷到多少钱?

方法一(记忆化搜索法)

本题的解题思路可通过如下递归树来表示

 对于本题的状态定义如下

对于本题的状态转移方程定义如下

很显然有大量的重叠子问题且有最优子结构存在,所以可以考虑用记忆化搜索的方法(自顶向下)予以解决,具体实现思路见代码与注释。

解题代码如下:

class Solution{
private:
    //用memo数组实现记忆化功能
    vector<int> memo;
    int findrob( vector<int>& nums, int index ){
        //递归终止条件
        if( index >= nums.size() ) return 0;
        //若memo[index]被计算过,则直接使用即可,避免重复计算
        if( memo[index] != -1)  return memo[index];

        //若memo[index]没被计算过,则先计算得到res后再赋值给memo[index],以便后面使用
        int res = 0;
        for ( int i = index; i < nums.size(); i++ ) {
            res = max( res, nums[i] + findrob(nums, i+2) );
        }
        memo[index] = res;
        return res;
    }


public:
    int rob( vector<int>& nums ){
        //由于抢劫的区间是(0,nums.size()-1),所以memo大小只需要初始化为n即可
        memo = vector<int>(nums.size(), -1);
        return findrob( nums, 0 );
    }
};

提交后的结果如下:

 

方法二(动态规划法)

考虑维护一个数组memo,用两次for循环自底向上依次记录偷到每个房子时,偷窃金额的最大值,其中外层循环 i 控制偷房子的范围,内层 for 循环控制在给定范围内偷房子的组合。最后返回 memo[0] 即可。

解题代码如下:

class Solution{
public:
    int rob( vector<int>& nums ){
        int n = nums.size();
        if( n == 0 ) return 0;
        vector<int> memo(n, -1);
        memo[n-1] = nums[n-1];
        //在[i,...n-1]范围内偷房子
        for (int i = n - 2; i >= 0; i--) {
            //考虑从j=i开始偷,依次遍历
            for (int j = i; j < n; j++) {
                memo[i] = max( memo[i], nums[j] + (j + 2 < n ? memo[j+2] : 0 ));
            }
        }

        return memo[0];
    }
};

提交后的结果如下:

 

 

 

日积月累,与君共进,增增小结,未完待续。


转载:https://blog.csdn.net/Vensmallzeng/article/details/99546616
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场