213. House Robber II

1、Description
213. House Robber II
2、题解思路
该问题和之前的House Robber I问题基本类似,只不过多了一个小变化,就是所有的城市现在围成一个环状,也就是多了个限制:不允许数组头尾的两家银行同时被盗。由House Robber I不难得到递推方程rob[i]=maxrob[i2]nums[i],rob[i1]rob[i]=max{rob[i-2]*nums[i] ,rob[i-1]},其中rob[i]表示从城市0抢到城市i所能得到的最大金额。那么问题来了如何在House Robber I的基础上进行改进呢,最直观的就是由于头尾元素之间是互斥的,那么我们就利用上述递推方程连续求解两次,一次去掉头城市,一次去掉尾城市。然后取两次求解中的最大值即可.

3、代码实现(java)
代码的基本操作只用到了一层for循环,时间复杂度为O(n),额外开辟一个数组rob,空间复杂度为O(n)

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]);
        if(nums.length==3) return Math.max(Math.max(nums[0],nums[1]),nums[2]);
        int[] rob = new int[nums.length-1];
        //remove the head
        rob[0] = nums[1];
        rob[1] = Math.max(rob[0],nums[1+1]);
        for(int i = 2;i<nums.length-1;i++){
            rob[i] = Math.max(rob[i-2]+nums[i+1],rob[i-1]);
        }
        int removehead = rob[nums.length-2];                                                   
        // System.out.println(Arrays.toString(rob));
        //remove the tail
        rob[0] = nums[0];
        rob[1] = Math.max(rob[0],nums[1]);
        for(int i = 2;i<nums.length-1;i++){
            rob[i] = Math.max(rob[i-2]+nums[i],rob[i-1]);
        }
        int removetail = rob[nums.length-2];                                                           //System.out.println(Arrays.toString(rob));
        return Math.max(removehead,removetail);
        
    }
}