Leetcode高频题:213打家劫舍II

题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

题目描述

你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。

给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额。

示例 1:

输入:nums = [2,3,2]
输出:3
解释:你不能先偷窃 1 号房屋(金额 = 2),然后偷窃 3 号房屋(金额 = 2), 因为他们是相邻的。

示例 2:

输入:nums = [1,2,3,1]
输出:4
解释:你可以先偷窃 1 号房屋(金额 = 1),然后偷窃 3 号房屋(金额 = 3)。
     偷窃到的最高金额 = 1 + 3 = 4 。

示例 3:

输入:nums = [1,2,3]
输出:3

提示:

  • 1 <= nums.length <= 100
  • 0 <= nums[i] <= 1000

跟我之前写的打家劫舍1的解法只是当前数组能不能成环,不成环就是头尾互不影响,成环就是头尾互相影响,选这个就不能选那个

具体看代码

package dataStructure.bigFactory.chapter33;

/**
 * 你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。
 *
 * 给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额。
 *
 *
 *
 * 示例 1:
 *
 * 输入:nums = [2,3,2]
 * 输出:3
 * 解释:你不能先偷窃 1 号房屋(金额 = 2),然后偷窃 3 号房屋(金额 = 2), 因为他们是相邻的。
 * 示例 2:
 *
 * 输入:nums = [1,2,3,1]
 * 输出:4
 * 解释:你可以先偷窃 1 号房屋(金额 = 1),然后偷窃 3 号房屋(金额 = 3)。
 *      偷窃到的最高金额 = 1 + 3 = 4 。
 * 示例 3:
 *
 * 输入:nums = [1,2,3]
 * 输出:3
 *
 *
 * 提示:
 *
 * 1 <= nums.length <= 100
 * 0 <= nums[i] <= 1000
 */
public class _213HouseRobberII {
    /**
     * 题意太长,我总结一下对比打家劫舍1的区别就是当前的数组可以认为是一个环,0和N-1也相邻
     * 所以放0的话就不能放N-1,方N-1的话就不能放0
     * @param nums
     * @return
     */
    public int rob(int[] nums) {
        /**
         * 题目规定了数据范围,这里不会走,所以你爱写不写,我是个人习惯
         */
        if(nums == null || nums.length == 0) {
            return 0;
        }
        int N = nums.length;
        if(N == 1) {
            return nums[0];
        }
        if(N == 2) {
            return Math.max(nums[0], nums[1]);
        }
        /**
         * 大于2的情况的处理,使用动态规划,先定义两个dp数组:dpFromZero和dpFromOne
         * dpFromZero[i]表示是从0~i的最大收益
         * dpFromOne[i]表示1~i+1的最大收益,这个比较特殊,i=0代表1~1,i=1代表1~2
         * 这里有两个原因要这么写:1 为了不浪费0位置 2 为了和dpFromZero对齐,最后都取[N-2]
         * 如果你不能理解就成成长度=N,然后遍历从1开始也无所谓
         */
        int[] dpFromZero = new int[N - 1];
        int[] dpFromOne = new int[N - 1];
        /**
         * 简单的初始化过程:初始化前两个值
         * 第一个没得选择,第二个从前两个价值里选最大
         */
        dpFromZero[0] = nums[0];
        dpFromZero[1] = Math.max(nums[0], nums[1]);
        dpFromOne[0] = nums[1];
        dpFromOne[1] = Math.max(nums[1], nums[2]);
        /**
         * 初始化dp[0]和[1]之后,从2开始剩余的赋值(最大N-2)
         * 这里从2开始是因为0和1位置可以特殊处理,然后后面每个位置i依赖于i-1和i-2的值
         */
        for(int i = 2; i < N - 1; i++) {
            /**
             * 当前位置的选择:1 当前位置的不要,等同于dpFromZero[i-1] 2 当前位置要,加上0~i-2能获得的最大价值(dpFromZero[i-2])
             * 二者取最大
             */
            dpFromZero[i] = Math.max(dpFromZero[i - 1], nums[i] + dpFromZero[i -2]);
            /**
             * dpFromOne同理,只是当前位置的值这里要注意不是nums[i],而是nums[i+1]
             */
            dpFromOne[i] = Math.max(dpFromOne[i - 1], nums[i + 1] + dpFromOne[i - 2]);
        }
        return Math.max(dpFromZero[N-2], dpFromOne[N-2]);

    }
}

提交结果:

Leetcode高频题:213打家劫舍II_第1张图片

看不懂欢迎私信交流

你可能感兴趣的:(Leetcode,数据结构与算法,高频面试题,leetcode,算法,职场和发展)