Leetcode:House Robber II

简介: Leetcode:House Robber II

介绍

1668505085530.jpg

这是 House Robber II,也就是 I 的变型版本。II 和 I 的最大区别在于 II 把房子围成一个圈了这意味着第一幢房子和最后一幢房子是紧挨着的。根据规则,两间相邻的房子不能同时偷,小偷打击还是蛮大的

1668505098612.jpg

小偷在不触发报警装置的情况下,针对这类场景,如何让自己偷窃的利益最大化?


解题


上面提到,相邻两家不能同时偷。但是如果只有一家,那么构不成相邻的条件,就偷唯一的那户人家。

如果有两家,那么偷的必然是两家中钱多的那家。

那如果总数大于 2 家呢?

对于第 n 家来说,只有两种选择:偷或者不偷。

是咋么计算出当前这家是否要偷的呢。

我们假设当前这家编号为 n,那么,


max(偷第 n 家的钱 + dp[截止第 n-2 家偷的钱], dp[截止第 n-1 家偷的钱])。


这才是这道关于动态规划最核心的一个点。

看懂了吗?没看懂也没关系,手把手摸个图片出来。

1668505119045.jpg

最后,还需要考虑一个问题,如何确保偷了第一家就不偷最后一家,偷最后一家就不偷第一家的情况。 很简单,直接定义两个 dp,一个范围不包括第一家,一个范围不包括最后一家。 最后我们变成了求:


// 伪代码
最佳偷钱:=max(dp[不包括第一家],dp[不包括最后一家])


那么剩下的就是对两个 dp 的状态转移公式了

func rob(nums []int) int {
  n := len(nums)
  if n == 0 {
    return 0
  }
  if n == 1 {
    return nums[0]
  }
  dp1, dp2 := make([]int, n), make([]int, n)
  dp1[0] = nums[0]
  dp1[1] = max(dp1[0], nums[1])
  dp2[0] = 0 //dp2 不偷第一家
  dp2[1] = max(dp2[0], nums[1])
  for i := 2; i < n; i++ {
    if i < n-1 { // dp1 不偷最后一家
      dp1[i] = max(dp1[i-1], dp1[i-2]+nums[i])
    } else {
      dp1[i] = dp1[i-1]
    }
    dp2[i] = max(dp2[i-1], dp2[i-2]+nums[i])
  }
  return max(dp2[n-1], dp1[n-1])
}
func max(x int, y int) int {
  if x > y {
    return x
  }
  return y
}

其实代码还能更简洁

func rob(nums []int) int {
  n := len(nums)
  if n == 0 {
    return 0
  }
  if n == 1 {
    return nums[0]
  }
  if n == 2 {
    return max(nums[0], nums[1])
  }
  return max(helper(nums[1:]), helper(nums[:n-1]))
}
func helper(nums []int) int {
  first, second := nums[0], max(nums[0], nums[1])
  for _, v := range nums[2:] {
    first, second = second, max(second, first+v)
  }
  return second
}
func max(a, b int) int {
  if a > b {
    return a
  }
  return b
}


今天的题就分享到这了。

相关文章
|
安全
Leetcode 198. House Robber
一句话理解题意,有个偷马贼晚上要偷尽可能值钱的马,但连续两头马被偷会触发报警,问他如何在不触发报警(不偷连续的两匹马)的情况下偷到总价值最高马,返回最高总价值。
50 3
LeetCode 337. House Robber III
在上次打劫完一条街道之后和一圈房屋后,小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为“根”。 除了“根”之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫,房屋将自动报警。 计算在不触动警报的情况下,小偷一晚能够盗取的最高金额。
60 0
LeetCode 337. House Robber III
|
安全
LeetCode 213. House Robber II
你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都围成一圈,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。
79 0
LeetCode 213. House Robber II
【LeetCode】House Robber III(337)
The thief has found himself a new place for his thievery again. There is only one entrance to this area, called the "root." Besides the root, each house has one and only one parent house. After a tour, the smart thief realized that "all houses in this place forms a binary tree". It will automaticall
98 0
|
C++
LeetCode 198 House Robber(强盗盗窃最大值)(动态规划)(*)
版权声明:转载请联系本人,感谢配合!本站地址:http://blog.csdn.net/nomasp https://blog.csdn.net/NoMasp/article/details/50560560 翻译 你是一个专业强盗,并计划沿街去盗窃每一个住户。
928 0
|
2月前
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
|
3月前
|
Python
【Leetcode刷题Python】剑指 Offer 32 - III. 从上到下打印二叉树 III
本文介绍了两种Python实现方法,用于按照之字形顺序打印二叉树的层次遍历结果,实现了在奇数层正序、偶数层反序打印节点的功能。
56 6
|
3月前
|
搜索推荐 索引 Python
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
113 2
|
18天前
|
机器学习/深度学习 人工智能 自然语言处理
280页PDF,全方位评估OpenAI o1,Leetcode刷题准确率竟这么高
【10月更文挑战第24天】近年来,OpenAI的o1模型在大型语言模型(LLMs)中脱颖而出,展现出卓越的推理能力和知识整合能力。基于Transformer架构,o1模型采用了链式思维和强化学习等先进技术,显著提升了其在编程竞赛、医学影像报告生成、数学问题解决、自然语言推理和芯片设计等领域的表现。本文将全面评估o1模型的性能及其对AI研究和应用的潜在影响。
16 1