Back
Featured image of post House Robber打家劫舍

House Robber打家劫舍

打家劫舍系列问题

House Robber 打家劫舍

经典dp问题 , 如何获取最大金额

198. 打家劫舍

隔间偷窃 , 判断 [A + C , B]

     public int rob(int[] nums) {
         //一维dp
        int n = nums.length;
        if (n == 0) {
            return 0;
        } else if (n == 1) {
            return nums[0];
        }

        int[] dp = new int[n + 1];
        dp[0] = nums[0];
        dp[1] = Math.max(nums[0], nums[1]);

        for (int i = 2; i < n; i++) {
            dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1]);
        }

        return dp[n - 1];
    }

    public int robOPT(int[] nums) {
        int n = nums.length;
        if (n == 0) {
            return 0;
        } else if (n == 1) {
            return nums[0];
        } 
        int dp_i_0 = 0, dp_i_1 = 0;
        int dp_i = 0;
        for (int num : nums) {
            dp_i = Math.max(dp_i_1, dp_i_0 + num);
            dp_i_0 = dp_i_1;
            dp_i_1 = dp_i;
        }
        return dp_i;
    }
        //int first = nums[0], second = Math.max(nums[0], nums[1]);
        //for (int i = 2; i < length; i++) {
        //    int temp = second;
        //    second = Math.max(first + nums[i], second);
        //    first = temp;
        //}
        //return second;

213. 打家劫舍 II

首尾相连,形成了一个环,和198差不多做法,分成[0 , n-2] 和 [1 , n-1]两部分处理即可

    public int rob2(int[] nums) {
        int n = nums.length;
        if (n == 0) {
            return 0;
        } else if (n == 1) {
            return nums[0];
        } else if (n == 2) {
            return Math.max(nums[0], nums[1]);
        }

        //分成两部分去解决问题 , 偷nums[0]不偷n , 偷nums[1]就正常进行
        return Math.max(robDist(nums, 0, n - 2), robDist(nums, 1, n - 1));
    }

    private int robDist(int[] nums, int begin, int end) {
        int first = nums[begin], second = Math.max(nums[begin], nums[begin + 1]);
        for (int i = begin + 2; i <= end; i++) {
            int tmp = second;
            second = Math.max(first + nums[i], second);
            first = tmp;
        }
        return second;
    }

337. 打家劫舍 III

这波啊是二叉树打劫,依旧不能抢相连的,偷root不偷root.left / root.right

    //在二叉树上rob
    Map<TreeNode, Integer> memos = new HashMap<>();

    public int rob3(TreeNode root) {
        return robTree(root);
    }

    private int robTree(TreeNode root) {
        if (root == null) {
            return 0;
        }
        if (memos.containsKey(root)) {
            return memos.get(root);
        }

        int rob = root.val + (root.left == null ? 0 : robTree(root.left.left) + robTree(root.left.right)) +
                (root.right == null ? 0 : robTree(root.right.left) + robTree(root.right.right));
        int not = robTree(root.left) + robTree(root.right);
        int ans = Math.max(rob, not);
        memos.put(root, ans);
        return ans;
    }

    public int rob3OPT(TreeNode root) {
        int[] res = dp(root);
        return Math.max(res[0], res[1]);
    }

    /* 返回一个大小为 2 的数组 arr
    arr[0] 表示不抢 root 的话,得到的最大钱数
    arr[1] 表示抢 root 的话,得到的最大钱数
    */
    public int[] dp(TreeNode root) {
        if (root == null)
            return new int[]{0, 0};
        int[] left = dp(root.left);
        int[] right = dp(root.right);

        int rob = root.val + left[0] + right[0];
        int not_rob = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);

        return new int[]{not_rob, rob};
    }
Welcome to the world of Minezeratul