• House Robber II


    House Robber II

    问题:

    Note: This is an extension of House Robber.

    After robbing those houses on that street, the thief has found himself a new place for his thievery so that he will not get too much attention. This time, all houses at this place are arranged in a circle. That means the first house is the neighbor of the last one. Meanwhile, the security system for these houses remain the same as for those in the previous street.

    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.

    思路:

      动态规划

    我的代码1:

    public class Solution {
        public int rob(int[] nums) {
                if(nums == null || nums.length == 0)    return 0;
                int len = nums.length;
                if(len == 1) return nums[0];
                if(len == 2) return Math.max(nums[0],nums[1]);
                int max = Integer.MIN_VALUE;
                
                for(int i=0; i<len; i++)
                {
                    if(len == 3)
                        max = Math.max(max,nums[i]);
                    else if(len == 4)
                        max = Math.max(max, nums[i]+nums[(i+2)%len]);
                    else if(len == 5)
                        max = Math.max(max, nums[i]+Math.max(nums[(i+2)%len], nums[(i+3)%len]));
                    else
                    {
                        int[] result = new int[len-3];
                        int k = 0;
                        result[k++] = nums[(i+2)%len];
                        result[k++] = Math.max(nums[(i+2)%len],nums[(i+3)%len]);
                        for(int j = (i+4)%len; j != (i-1+len)%len; j = (j+1)%len,k++)
                        {
                            result[k] = Math.max(result[k-1],nums[j]+result[k-2]);
                        }
                        max = Math.max(max, result[len-4]+nums[i]);
                    }
                }
                return max==Integer.MIN_VALUE?0:max;
            }
    }
    View Code

    我的代码2:

    public class Solution {
        public int rob(int[] nums) {
                if(nums == null || nums.length == 0)    return 0;
                int len = nums.length;
                if(len == 1) return nums[0];
                if(len == 2) return Math.max(nums[0],nums[1]);
                return Math.max(rob(nums, 1, 0), rob(nums, 2, 1));
         }
        public int rob(int[] nums, int l, int h) {
            int len = nums.length;
            int[] result = new int[len-1];
            int k = 0;
            result[k++] = nums[l];
            result[k++] = Math.max(nums[(l+1)%len],nums[l]);
            for(int j=(l+2)%len; j!=h; j=(j+1)%len,k++)
            {
                result[k] = Math.max(result[k-1],nums[j]+result[k-2]);
            }
            return result[len-2];
        }
    }
    View Code

    他人代码:

    public class Solution {
        public int rob(int[] nums) {
                if(nums == null || nums.length == 0)    return 0;
                if(nums.length == 1)    return nums[0];
                int n = nums.length;
                return Math.max(robHelper(Arrays.copyOfRange(nums,0,n-1)),robHelper(Arrays.copyOfRange(nums,1,n)));
            }
           public int robHelper(int[] nums) {
            if(nums==null || nums.length==0)    return 0;
            if(nums.length == 1)    return nums[0];
            int len = nums.length;
            int[] max = new int[len];
            max[0] = nums[0];
            max[1] = Math.max(nums[0],nums[1]);
            
            for(int i=2; i<len; i++)
            {
                max[i] = Math.max(max[i-1], nums[i]+max[i-2]);
            }
            
            return max[len-1];
        }
    }
    View Code

    学习之处:

    • 代码的思想都是把圈的问题划分成直线的问题,第一次代码考虑的思路是划分圈的方式是尝试是否取每一个节点,取这个节点的时候划分圆圈为直线。时间复杂度是O(n*n),考虑的过程是01背包的思想
    • 第二次代码的思路是划分圈的方式是第一个和第二个节点必定有一个是最后不取的,所以按照这个理论可以不取第一个节点然后划圈为直线,或者不取第二个节点划圈为直线(好思路啊,看了别人的解释才恍然大悟),时间复杂度是O(n)
    • result[k++]方式尽量少用,用着用着就不知道什么地方出错了,为了cool代码出错可不值得。
    • 逆向思维不仅取决于递归转换成动态规划,逆向思维也表现在一个思路是尝试取这个节点看看是否合适,然后再依次遍历尝试其他节点,另外一个思路便是必有一个节点不取。
    • 他人的思路真是精妙,既然0和n-1在循环的条件下不能同时取到,那么该问题可以转换成等价的两个子问题,分别是0到n-2和1到n-1二者最大值即为要求的结果,II问题总是可以在I问题上进行发挥,也就是可以通过I问题可以解决II问题,学会进行复用!!!
  • 相关阅读:
    运行缓慢的查询语句
    EditPlus 替换所有文件夹下的文件包含子文件夹
    PRM–pageLoaded事件
    DataSet接收XML数据并按条件搜索
    复杂数据类型使用基础
    WebService客户端调用错误处理
    仿GOOGLE个性首页可移动图层效果
    asp.net 2.0中md5密码加密
    页面上的可鼠标移动内嵌页面层,并有关闭按钮,背景不可点击
    最好的。NET反编译工具
  • 原文地址:https://www.cnblogs.com/sunshisonghit/p/4534787.html
Copyright © 2020-2023  润新知