leetcode 198 & 213:House Robber

来源:互联网 发布:智能电视机软件下载 编辑:程序博客网 时间:2024/05/29 17:32

一.House Robber I 的题意是:有一排商铺,强盗不能连续抢劫相邻的两家,否则会触动报警器,求强盗在不触动报警器的前提下,可以抢劫的最多金钱总和。(输入一维数组,从中选择若干个数,使得这些数的和最大,并且这些数互不相邻):

本题可以用两种方法解决:自顶向下(递归,直观)和自底向上(递推,动态规划的思想,时复低于前者),先介绍递归方法,我们可以认为有n个商铺,走到第m家商铺面,能获得的最大金额总和为两种情况中的最大值:Math.max(nums[m]+solve(m-2),solve(m-1)),所以代码如下:

public static int rob1(int[] nums) {    return solve(nums.length-1,nums);}private static int solve(int index, int[] nums) {if(index <0 ){return 0;}int max = Math.max(nums[index]+solve(index-2,nums), solve(index-1,nums));return max;}
这种方法非常耗时,因为有很多冗余计算(画个图便可以看出),所以改用第二中方法,动态规划。我们开一个数组,记录那些已经算过的子问题的解,这样就只需查数组不需要计算多次,所以将递归改为递推,递推公式基本不变,代码如下:

public class Solution {    private int[] result;    public int rob(int[] nums) {        if(nums.length<=0){            return 0;        }        if(nums.length==1){            return nums[0];        }        int length = nums.length;        result = new int[length];  //result数据用于记录子问题的解,然后递推        result[0] = nums[0];       //以下两行定义边界情况        result[1] = Math.max(nums[0],nums[1]);        for(int i=2;i<length;i++){        //开始递推,递推公式没变            result[i] = Math.max(nums[i]+result[i-2],result[i-1]);        }        return result[length-1];    }}
二.House Robber II的题意是:这些商铺不是一排了,而是围成了一个圈,这样以前数组的第一个元素与最后一个元素也变成相邻的,其他要求不变,仍然是找出若干个不相邻的数,使他们的和最大。

思路:这道题在上一道的基础上加了限制,即抢了第一家就不能抢最后一家,抢了最后一家就不能抢第一家。所以分为两种情况分别进行计算,最后返回这两种情况中结果最大一个即为所求,我们这次要开两个数组,分别记录这两种情况的子问题的题,其他地方思路不变(边界的定义,递推公式均不变,只是数组为两个不同的数组而已),代码如下:

public class Solution {    public int rob(int[] nums) {        if(nums.length <=0)        return 0;        if(nums.length ==1)        return nums[0];        if(nums.length ==2)        return Math.max(nums[0], nums[1]);        int[] dp1 = new int[nums.length-1];  //记录第1个到倒数第2个        int[] dp2 = new int[nums.length-1];  //记录第2个到倒数第1个        dp1[0] = nums[0];        dp1[1] = Math.max(nums[0], nums[1]);        dp2[0] = nums[1];        dp2[1] = Math.max(nums[1], nums[2]);        for(int i=2;i<nums.length-1;i++){        dp1[i] = Math.max(nums[i]+dp1[i-2], dp1[i-1]);        dp2[i] = Math.max(nums[i+1]+dp2[i-2], dp2[i-1]);        }        return Math.max(dp1[nums.length-2], dp2[nums.length-2]);     }}





1 0
原创粉丝点击