【LeetCode】337. House Robber III 解题报告(Python)
作者: 负雪明烛
id: fuxuemingzhu
个人博客: http://fuxuemingzhu.cn/
题目地址:https://leetcode.com/problems/house-robber-iii/description/
题目描述
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 automatically contact the police if two directly-linked houses were broken into on the same night.
Determine the maximum amount of money the thief can rob tonight without alerting the police.
Example 1:
3
/ \
2 3
\ \
3 1
Maximum amount of money the thief can rob = 3 + 3 + 1 = 7.
Example 2:
3
/ \
4 5
/ \ \
1 3 1
Maximum amount of money the thief can rob = 4 + 5 = 9.
题目大意
从一棵二叉树中取出一些数字,使得取得数字的和最大。取的规则是不能同时取直接相连的两个节点。
解题方法
这个是限定规则下的博弈过程。曾经看过左程云的视频教程,对这个过程印象比较深刻。
本题的做法,就是求本节点+孙子更深节点
vs儿子节点+重孙更深的节点
的比较。
道理能想明白,代码有点难写。用了dfs函数,虽然递归是自顶向下的,但是因为是不断的return,所以真正求值是从底向上的。用到了一个有两个元素的列表,分别保存了之前层的,不取节点和取节点的情况。然后遍历左右子树,求出当前节点取和不取能得到的值,再返回给上一层。注意这个里面的robcurr是当前节点能达到的最大值,所以最后返回结果的时候试试返回的root节点robcurr的值。
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def rob(self, root):
"""
:type root: TreeNode
:rtype: int
"""
def dfs(root):
# from bottom to top
if not root: return [0, 0] # before layer, no robcurr, robcurr
robleft = dfs(root.left)
robright = dfs(root.right)
norobcurr = robleft[1] + robright[1]
robcurr = max(root.val + robleft[0] + robright[0], norobcurr)
return [norobcurr, robcurr]
return dfs(root)[1]
二刷的时候换了一种解法,使用的仍然是递归,不过不用返回两个值,而是直接一个值:无论用还是不用情况下,能得到的最好结果。必须使用记忆化递归,否则超时。
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def rob(self, root):
"""
:type root: TreeNode
:rtype: int
"""
memo = dict()
return self.helper(root, memo)
def helper(self, root, memo):
if not root:
return 0
if root in memo:
return memo[root]
res = 0
notused = self.helper(root.left, memo) + self.helper(root.right, memo)
used = 0
if root.left:
used += self.helper(root.left.left, memo) + self.helper(root.left.right, memo)
if root.right:
used += self.helper(root.right.left, memo) + self.helper(root.right.right, memo)
res = max(notused, used + root.val)
memo[root] = res
return res
三刷的时候,代码思路更简洁明了。递归函数增加一个变量,表示当前节点的父亲节点是否用过。根节点没有父亲节点,所以其父亲节点肯定没用过。然后我们判断在某个节点的父亲用过和没用过的情况下,当前节点能不能用,最优的结果分别是多少。
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def rob(self, root):
"""
:type root: TreeNode
:rtype: int
"""
self.d = dict()
return self.helper(root, False)
def helper(self, root, parentUsed):
if not root: return 0
if (root, parentUsed) in self.d:
return self.d[(root, parentUsed)]
res = 0
if parentUsed:
res = self.helper(root.left, False) + self.helper(root.right, False)
else:
res = max(root.val + self.helper(root.left, True) + self.helper(root.right, True), self.helper(root.left, False) + self.helper(root.right, False))
self.d[(root, parentUsed)] = res
return res
日期
2018 年 6 月 22 日 —— 这周的糟心事终于完了
2018 年 12 月 25 日 —— 圣诞节快乐
2019 年 3 月 23 日 —— 周末加油鸭
【LeetCode】337. House Robber III 解题报告(Python)的更多相关文章
- Leetcode 337. House Robber III
337. House Robber III Total Accepted: 18475 Total Submissions: 47725 Difficulty: Medium The thief ha ...
- [LeetCode] 337. House Robber III 打家劫舍 III
The thief has found himself a new place for his thievery again. There is only one entrance to this a ...
- [LeetCode] 337. House Robber III 打家劫舍之三
The thief has found himself a new place for his thievery again. There is only one entrance to this a ...
- Java [Leetcode 337]House Robber III
题目描述: The thief has found himself a new place for his thievery again. There is only one entrance to ...
- 【LeetCode】62. Unique Paths 解题报告(Python & C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址:https://leetcode.com/problems/unique-pa ...
- LeetCode 337. House Robber III 动态演示
每个节点是个房间,数值代表钱.小偷偷里面的钱,不能偷连续的房间,至少要隔一个.问最多能偷多少钱 TreeNode* cur mp[{cur, true}]表示以cur为根的树,最多能偷的钱 mp[{c ...
- 【LeetCode】556. Next Greater Element III 解题报告(Python)
[LeetCode]556. Next Greater Element III 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzhu 个人 ...
- 【LeetCode】376. Wiggle Subsequence 解题报告(Python)
[LeetCode]376. Wiggle Subsequence 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.c ...
- 【LeetCode】649. Dota2 Senate 解题报告(Python)
[LeetCode]649. Dota2 Senate 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地 ...
随机推荐
- excel-大于0的数值标记红色且标记红色上箭头,小于0的数值标记绿色且标记绿色下箭头,等于0的数值标记黄色且标记右箭头
0.数值是常规的数值: [蓝色]"↑"0;[红色]"↓"0;[黄色]"→"0 [蓝色]"↑"0.0;[红色]" ...
- gcc 引用math 库 编译的问题 解决方法
1.gcc app.c -lm 其中lm表示的是连接 m forlibm.so / libm.a表示你想要的库 abc for libabc.so / libabc.a 其中.a表示的是静态链接库 . ...
- 『与善仁』Appium基础 — 17、元素定位工具(一)
目录 1.uiautomatorviewer介绍 2.uiautomatorviewer工具打开方式 3.uiautomatorviewer布局介绍 4.uiautomatorviewer工具的使用 ...
- linux 实用指令时间日期类
linux 使用指令时间日期类 data 显示当前日期 基本语法 date 显示当前时间 date+%Y 显示当前年份 date+%m 显示当前月份 date+%d 显示当前是哪一天 date &qu ...
- adjective
形容词用来描述名词或代词:副词用来描述剩下的(动词.形容词.副词和整句).adverb: to word. Adjectives are used almost exclusively to modi ...
- 利用python代码获取文件特定的内容,并保存为文档
说明:有段时间需要读取上百个文件的单点能(sp),就写了下面的代码(计算化学狗努力转行中^-^) import os.path import re # 1 遍历指定目录,显示目录下的所有文件名 def ...
- nodejs-Child Process模块
JavaScript 标准参考教程(alpha) 草稿二:Node.js Child Process模块 GitHub TOP Child Process模块 来自<JavaScript 标准参 ...
- C++福尔摩斯的约会
这道题的要求总结如下: 1.DAY 星期 大写字母:A B C D E F G2.HH 时 数字+大写字母 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M ...
- System.exit(-1)和return 的区别
对于只有一个单一方法的类或者系统来说是一样的,但是对于含有多个类和方法,且调用关系比较复杂时就不一样了. System.exit(-1)是指所有程序(方法,类等)停止,系统停止运行. return只是 ...
- SpringBoot自定义控制层参数解析
一.背景 在Spring的Controller中,我们通过@RequestParam或@RequestBody就可以将请求中的参数映射到控制层具体的参数中,那么这个是怎么实现的呢?如果我现在控制层中的 ...