壹 ❀ 引

本题来自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. 腾讯视频客户端 MP4 下载

    腾讯视频直接使用客户端下载视频,得到的是 QLV 文件,这种加密视频文件只能通过腾讯视频客户端播放.最新版的腾讯客户端下载的 QLV 文件,使用各种转码软件都不能正常转码.从服务器下载的 TS 文件一 ...

  2. 使用zipFile读取文件时遇到的问题及解决(KeyError: "There is no item named 'xxx' in the archive")

    问题描述 在Windows上跑一段代码时,遇到如下问题: KeyError: "There is no item named 'CDR_Data\\\\CDR.Corpus.v010516\ ...

  3. [kubernetes]安装dashboard

    前言 kubernetes官方文档中的web UI网页管理工具是kubernetes-dashboard,可提供部署应用.资源对象管理.容器日志查询.系统监控等常用的集群管理功能.为了在页面上显示系统 ...

  4. CSS - 怎么样在不同分辨率的情况下计算根元素需要的font-size的值

    一般我们做页面,肯定都会有设计图,移动端页面,一般情况下,UI出图都会定宽为640px,这也是移动端的标准尺寸:但是,我们也不能排除可能有其他特殊的情况可能需要做其他大小的设计图.所以,我们可以先定一 ...

  5. [转帖]redis 持久化方式 - aof 和 rdb 区别

    https://wenfh2020.com/2020/04/01/redis-persistence-diff/   aof 和 rdb 是 redis 持久化的两种方式.我们看看它们的特点和具体应用 ...

  6. Linux用户以及ssh安全相关设置

    Linux用户相关操作 摘要 最近重保, 需要进行网络安全防护. 部分同事处理过程总是顺序有一些不太对的情况. 同时发现自对Linux用户设置也存在很多不清不楚的地方 所以趁着周末学习和总结一下. 用 ...

  7. [转帖]Java 类加载器

      类的生命周期和加载过程 在Java中数据类型分为基本数据类型和引用数据类型.基本数据类型由虚拟机预先定义,引用数据类型则需要进行类的加载.引用类型,Java 将其细分为四种:类.接口.数组类和泛型 ...

  8. CentOS8 的容器运行时解决中文乱码问题的一个思路

    首先说明一下 CentOS7和CentOS8关于locale语言文件的位置是不一样的. Docker pull centos 拉取下来的镜像 一般是不带中文语言包的. 简单方法是在 CentOS之后安 ...

  9. 飞腾2000+银河麒麟v10安装redis的注意事项

    先说一下结论 无法复用ubuntu上面编译的二进制文件 无法直接使用docker官网下面的arm64的镜像运行 无法直接使用redis6.0.10最新版本编译运行 可以使用redis5.0.4 进行编 ...

  10. KubeSphere2.1踩坑记

    至少两台机器.推荐4X16.(完全安装KubeSphere会吃掉10G+内存) k8s安装(略1.14.8)可参考我上一篇文章或者基于kubeadmin快速安装 KubeSphere2.1前置条件 1 ...