LeetCode 198. House Robber

来源:互联网 发布:房地产数据网 编辑:程序博客网 时间:2024/06/09 21:43

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(n)的复杂度,当前规模问题的最优解只依赖与比他规模小的子问题。
  • 假设f(n)表示规模n时能抢劫的最大值,计算f(n)的递推关系可以这样算:如果n-1这个点抢了,那么f(n) = f(n-1) ;如果n-1这个点没抢,那么f(n) = f(n-2) + nums[n]。综上,f(n) = max{f(n-1), f(n-2) + nums[n] }
  • 把i从1加到n,计算出每一个f(i) 最终返回f(nums.size())即为最后结果。
class Solution {public:    int rob(vector<int>& nums) {        if(nums.size() == 0) return 0;        if(nums.size() == 1) return nums[0];        vector<int> mem(nums.size()+1);        mem[0] = 0;        mem[1] = nums[0];        for (int i = 2, n = nums.size(); i <= n; ++i) {            mem[i] = max(mem[i-1], mem[i-2]+nums[i-1]);        }        return mem[nums.size()];    }};

动态规划二

  • 动态规划用来解决多阶段决策的最优化问题。这道题是最优化问题,解有很多个,但是存在一个最大的解.
  • 想要使用动态规划需要满足两个要素:最优子结构 子问题重叠
  • 最优子结构是指原问题的最优解包括子问题的最优解;而且各个子问题之间相互独立,使用的资源没有冲突。这里想要求出[start, end]能抢劫的最大值,那么可以分解为两个子问题:抢劫[start, p] 和 [p+1, end]每一个子问题都应该是最优解,才能保证原问题是最优解,否则可以用剪切-粘贴原则证伪。那么子问题是不是相互独立的那?这里并不是,如果前一个选择抢劫p点,那么后一个子问题就不能抢劫p+1。我们可以通过重新划分下子问题来解决这个独立性问题。要想求出[start, end]的最大值,分解为两个子问题max{ [start,p-1] + [p+1, end], [start, p] + [p+2, end]} 也就是说对于p这个点如果前面抢,那么后面就要从p+2开始抢,如果前面不抢,那么后面就可以从p+1来抢。然后对于p点这个划分,取这两种情况的较大值。
  • 假设d(start,end)表示从[start, end]能抢的最大值,我们以这个作为状态。状态转移方程为 d(start,end)= max{ max{d(start, p-1) + d(p+1, end), d(start, p) + d(p+2, end)} } p属于[start, end-1]
  • 如果只是递归的话会TLE。使用自顶向下带备忘的DP才解决了这个问题,使用了一个二维数组,记录下算过的结果,之后再遇到直接查表就行了。
class Solution {public:    vector<vector<int> > array;    vector<int> nums;    int getMyRob(int start, int end)    {        int n = end - start + 1;        if(n <= 0) return 0;        if(n == 1) return nums[start];        if(n == 2) return max(nums[start], nums[end]);        if(array[start][end] != -INT_MAX) return array[start][end];        int maxRet = -INT_MAX;        for (int i = start; i <= end-1; ++i) {            //1.左边少一个;默认i对应的位置是给左边的            int max1 = getMyRob(start, i-1) + getMyRob(i+1, end);            //2.右边少一个            int max2 = getMyRob(start, i) + getMyRob(i+2, end);            if(max(max1, max2) > maxRet) maxRet = max(max1, max2);        }        array[start][end] = maxRet;        return maxRet;    }    int rob(vector<int>& nums) {        int n = nums.size();        if(n==0) return 0;        for (int i = 0; i < n; ++i) {            vector<int> line(n, -INT_MAX);            array.push_back(line);        }        this->nums = nums;        return getMyRob(0,nums.size()-1);    }};
原创粉丝点击