LeetCode 198. House Robber 递归->记忆->动态规划 ->新思路

来源:互联网 发布:监控设备搜索软件 编辑:程序博客网 时间:2024/05/18 00:09

198. House Robber

You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night.

Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.

题意

一个专业的小偷在一条街上偷取房屋内的宝物。 每个房屋内拥有不同的价值的宝物,唯一的限制是不能连续偷取相邻房屋,否则会自动触发报警器。问如何偷取才能使得到的价值最大。

思路

这里写图片描述
这里写图片描述

代码

  • 纯递归,含大量的重复计算超时

时间复杂度:O((2^N)*N)

class Solution {private:    //int res; 将res放在外边会记录历史值,而出错,之前支路的值会加到旁边的支路上    //偷取[index...n-1]房屋之间偷取宝物的最大和,index从0开始    int robMax(vector<int>nums,int index)    {        if(index > nums.size())   //[index(>n-1),n-1]集合为空,表示宝物为0            return 0;                int res = 0;  //所以每次都需要更新一下当前结果的最大值        for(int i=index;i<nums.size();i++)//根节点对应的各个分支,能偷取的最大值,选分支中最大的        {            res = max(res,nums[i]+robMax(nums,i+2));        }                return res;    }    public:    int rob(vector<int>& nums) {       return robMax(nums,0);    }};
  • 记忆化优化
class Solution {private:    vector<int> memo;    //int res; 将res放在外边会记录历史值,而出错,之前支路的值会加到旁边的支路上    //偷取[index...n-1]房屋之间偷取宝物的最大和,index从0开始    int robMax(vector<int>nums,int index)    {        if(index > nums.size())   //[index(>n-1),n-1]集合为空,表示宝物为0            return 0;        if(memo[index] != -1)        {            return memo[index];        }        int res = 0;  //所以每次都需要更新一下当前结果的最大值,层层往外比较        for(int i=index;i<nums.size();i++)  //分支        {            res = max(res,nums[i]+robMax(nums,i+2));        }        memo[index] = res;        return res;    }public:    int rob(vector<int>& nums) {       memo = vector<int> (nums.size()+1,-1);       return robMax(nums,0);          }};
  • 动态规划,子问题最优达到全局最优。当给定的房屋有n个,范围就是[0…n),memo[i] 表示抢劫 nums[i…n) 所能获得的最大收益
  • 最小子问题就是n-1房屋,区间[n-1,n),区间内只有一个元素memo[n-1]就是第n-1房屋内的价值
  • 之后从n-2开始,区间[n-2,n),区间内有n-2和n-1两个元素,不能选相邻元素。同时需要做一个越界判断。
class Solution {public:    int rob(vector<int>& nums) {       vector<int> memo(nums.size(),-1);  //记忆优化         // memo[i] 表示抢劫 nums[i...n) 所能获得的最大收益       memo[nums.size()-1] = nums[nums.size()-1];       for(int i = nums.size()-2;i>= 0;i--)       {            for(int j = i; j<nums.size(); j++)            {                memo[i] = max(memo[i], nums[j] + (j + 2 < nums.size() ? memo[j + 2] : 0) );            }       }       return memo[0];    }};

结果

这里写图片描述

新思路

class Solution {   public:       int rob(vector<int> &num) {           int best0 = 0;   // 表示没有选择当前houses           int best1 = 0;   // 表示选择了当前houses           for(int i = 0; i < num.size(); i++){               int temp = best0;               best0 = max(best0, best1); // 没有选择当前houses,那么它等于上次选择了或没选择的最大值               best1 = temp + num[i]; // 选择了当前houses,值只能等于上次没选择的+当前houses的money           }           return max(best0, best1);       }   };  
原创粉丝点击