0
点赞
收藏
分享

微信扫一扫

Java 订单超时自动取消策略

双井暮色 03-27 19:30 阅读 1

打家劫舍2

力扣原题链接

问题描述

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

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

示例

示例 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. 不偷窃第一个房屋,偷窃第二个房屋到最后一个房屋之间的房屋。
  2. 不偷窃最后一个房屋,偷窃第一个房屋到倒数第二个房屋之间的房屋。

对于每个子问题,可以使用动态规划求解。
请添加图片描述

状态定义

定义一个一维动态规划数组 dp,其中 dp[i] 表示偷窃第一个房屋到第 i 个房屋时的最高金额。

状态转移方程

对于每个房屋 nums[i],有两种选择:偷窃该房屋或者不偷窃该房屋。状态转移方程为:

dp[i] = max(dp[i-1], dp[i-2] + nums[i])

初始化

需要对动态规划数组进行初始化。初始时,dp[0] = nums[0]dp[1] = max(nums[0], nums[1])

Java解题

class Solution {
    // 主函数,计算环形盗窃计划的最大金额
    public int rob(int[] nums) {
        // 如果只有一个房屋,则直接返回该房屋的金额
        if (nums.length == 1) 
            return nums[0];
        // 分别计算不偷窃第一个房屋和不偷窃最后一个房屋的最大金额,取两者的较大值
        return Math.max(robRange(nums, 0, nums.length - 2), robRange(nums, 1, nums.length - 1));
    }

    // 辅助函数,计算偷窃指定范围内房屋的最大金额
    private int robRange(int[] nums, int start, int end) {
        // 初始化前一个房屋的最大金额和当前房屋的最大金额
        int prevMax = 0;
        int currMax = 0;
        // 遍历指定范围内的房屋
        for (int i = start; i <= end; i++) {
            // 临时保存当前房屋的最大金额
            int temp = currMax;
            // 更新当前房屋的最大金额,选择偷窃当前房屋或者不偷窃当前房屋
            currMax = Math.max(prevMax + nums[i], currMax);
            // 更新前一个房屋的最大金额
            prevMax = temp;
        }
        // 返回偷窃指定范围内房屋的最大金额
        return currMax;
    }
}

总结

通过环形动态规划的思想,我们可以解决这个问题。首先将问题分解为两个子问题,然后对每个子问题使用动态规划求解,最终返回两个子问题的最大值。

举报

相关推荐

0 条评论