壹 ❀ 引

本题来自LeetCode 213. 打家劫舍 II,难度中等,属于前面我们做过的198. 打家劫舍的升级版,难度同样为中等,题目描述如下:

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

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

示例 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 = [0]
输出:0

提示:

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

这里我还是推荐先尝试简单点的版本,因为核心思想不变,想做此题,还是得掌握动态规划解法的核心思想,上一道题的题解为JS Leetcode 198. 打家劫舍 题解分析,那么我们开始分析本题。

贰 ❀ 分治算法+动态规划

在上道题中,我们已经介绍了此题动态规划的核心思想,并推导出动态规划转移方程,即:

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

翻译过来就是第i家最大收益dp[i],为当前偷的这一家的收益 + 上上家收益与上家收益的最大值,比如例子1,4,2。到第三家时,我们能拿到的最大收益为Math.max(4,1+2),所以最终得到4。

而今天这一道题的唯一差异在于,现在的房屋形成了一个环。还是以[1,4,2]为例,两者的区别:

因为环的缘故,1,3家可以理解成并排的两家,所以没办法一起再偷了,才导致了右边这三种情况。有同学可能就想了,那为什么左边这种不存在只偷1,或者只偷第三家的情况呢?原因是上道题的房屋并不是环,且1,3一起偷并不冲突,能偷白不偷,总不可能存在偷了1,3两家的和比其中一家还小的情况吧。

让我们从简单的例子开始推倒,比如[1,4,2],按照上面的方案,可分为:

  • 不偷第一家,偷第二家或者第三家,看这两家中间谁更大,很明显4更大。
  • 不偷最后一家,偷第一家或者第二家,看这两家中谁更大,很明显4更大。
  • 第一家和第三家都不偷,直接偷第二家,很明显只能是4。

但是如果我们仔细思考,所谓第三种偷法,即不偷第一家和第三家只偷第二家的这种可能性,其实已经被包含在前两种偷法中了,因为如果中间这家最大,它总是能被找出来,比如第一种偷法因为4>2,导致最后还是只偷了第二家,而如果中间这家很小,它也总是能被排除掉。

我们最终得到了两种偷法,即要么不偷第一家,要么不偷最后一家,那知道了这个我们又该如何求出最大收益呢?到这里,我们需要引入一个很重要的概念,分治算法。

分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。---百度百科

所谓分治,即是分而治之(将一个问题的不同情况拆开分别处理),将一个大问题,拆分成多个小的且与原问题性质相同的问题。比如上面因为环的缘故,我们要么不偷第一家,从后面的收益中找最大收益,要么不偷最后一家,从前面的收益中找到最优解。那是不是可以直接分两种情况,分别求出小问题的最优解,然后总结这两者,找出全局问题真正的最优解呢。

综合上述,我们可以假定不偷第一家的最佳收益为P1,不偷最后一家的最佳收益为P2,那么全局最佳收益即是Math.max(P1,P2),而P1,P2的问题已经降级为昨天那道题的思路了,所以让我们来实现这段代码:

/**
* @param {number[]} nums
* @return {number}
*/
var rob = function (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]);
};
// 照搬上道题的方法
let findMax = function (nums) {
let n = nums.length;
let dp = new Array(n + 1);
dp[0] = 0;
dp[1] = nums[0];
for (let i = 2; i <= n; i++) {
dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i - 1]);
};
return dp[n];
};
// 不偷第一家,所以i从1开始
let P1 = findMax(nums.slice(1));
// 不偷最后一家,所以结尾为length-1
let P2 = findMax(nums.slice(0, nums.length - 1));
return Math.max(P1, P2);
};

代码看上去很长,其实大部分代码都是照搬了上道题的思路,那么本题就分析到这里了。

JS Leetcode 213. 打家劫舍 II 题解分析,在动态规划基础上感受分治算法的魅力的更多相关文章

  1. Java实现 LeetCode 213 打家劫舍 II(二)

    213. 打家劫舍 II 你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金.这个地方所有的房屋都围成一圈,这意味着第一个房屋和最后一个房屋是紧挨着的.同时,相邻的房屋装有相互连通的防盗 ...

  2. LeetCode 198. 打家劫舍(House Robber)LeetCode 213. 打家劫舍 II(House Robber II)

    打家劫舍 题目描述 你是一个专业的小偷,计划偷窃沿街的房屋.每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报 ...

  3. [LeetCode] 213. 打家劫舍 II

    题目链接:https://leetcode-cn.com/problems/house-robber-ii/ 题目描述: 你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金.这个地方所有 ...

  4. leetcode 213. 打家劫舍 II JAVA

    题目: 你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金.这个地方所有的房屋都围成一圈,这意味着第一个房屋和最后一个房屋是紧挨着的.同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻 ...

  5. 刷题-力扣-213. 打家劫舍 II

    213. 打家劫舍 II 题目链接 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/house-robber-ii/ 著作权归领扣网络所有.商业 ...

  6. [LeetCode] 198. 打家劫舍II ☆☆☆(动态规划)

    描述 你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金.这个地方所有的房屋都围成一圈,这意味着第一个房屋和最后一个房屋是紧挨着的.同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的 ...

  7. 力扣---213. 打家劫舍 II

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

  8. 213. 打家劫舍 II

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

  9. 1、线性DP 213. 打家劫舍 II

    https://leetcode-cn.com/problems/house-robber-ii/ //rob 0, not rob n-1 || not rob 0,not rob n-1 ==&g ...

  10. [LeetCode] 198. 打家劫舍 ☆(动态规划)

    描述 你是一个专业的小偷,计划偷窃沿街的房屋.每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警. 给定一个 ...

随机推荐

  1. asio 使用 openssl 示例

    #include <boost/asio.hpp> #include <boost/asio/ssl.hpp> #include <boost/algorithm/str ...

  2. kubernetes scc 故障排查小记

    1. 故障现象 环境在跑自动化测试时打印 error: [ ERROR ] Opening output file '/output.xml' failed: Read-only file syste ...

  3. DASCTF X CBCTF 2023|无畏者先行 CRYPTO—WP

    EzRSA 1.题目信息 from Crypto.Util.number import * import random from gmpy2 import * from libnum import * ...

  4. java - classpath 的配置

    classpath C:\Program Files\Java\jdk\jre\lib\rt.jar

  5. Laravel - 虚拟主机引入静态资源

    一. 注意: 引用的静态文件要放在根目录,不要放在assets目录下 二. 引入方法 1.  模板中引入 css      <link rel="stylesheet" hr ...

  6. [转帖]十分钟掌握 Vim 编辑器核心功能

    https://juejin.cn/post/6929248764746006535 前言 相信不论是前端还是后台多多少少都需要上到服务器上做一些操作,改改配置文件等,大多数 Linux 服务器默认都 ...

  7. [转帖]命令行非明文密码连接 TiDB

    https://tidb.net/blog/6794a34b#%E6%96%B9%E5%BC%8F%E4%B8%80%EF%BC%9A%E5%91%BD%E4%BB%A4%E8%A1%8C%E8%BE ...

  8. [转帖]linux按行读取 (while read line与for-loop)

    https://cloud.tencent.com/developer/article/1655435 在linux下一般用while read line与for循环按行读取文件.现有如下test.t ...

  9. FIO的再学习-不同Raid,不同磁盘性能验证

    FIO的再学习-不同Raid性能验证 背景 发现自己对iodepth的和num_jobs的理解存在偏差 找了一些资料才发现自己很多地方做的不对. 这里找到一个新资料可以进行模拟数据库的测试 测试配置文 ...

  10. [转帖]SPEC2006

    安装步骤 # Ubuntu16.04 # 注意安装gFortran . ./install.sh . ./shrc 一般情况下经过以上步骤即可安装完毕,进行使用,注意需要执行shrc设置完环境变量以后 ...