目录
337. 打家劫舍 III
https://leetcode-cn.com/problems/house-robber-iii/
在上次打劫完一条街道之后和一圈房屋后,小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为“根”。 除了“根”之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫,房屋将自动报警。
计算在不触动警报的情况下,小偷一晚能够盗取的最高金额。
示例 1:输入: [3,2,3,null,3,null,1]
输出: 7 解释: 小偷一晚能够盗取的最高金额 = 3 + 3 + 1 = 7.
示例 2:输入: [3,4,5,1,3,null,1]
输出: 9 解释: 小偷一晚能够盗取的最高金额 = 4 + 5 = 9.
题解
一:DFS+记忆化。
class Solution(object):
def __init__(self):
self.rec = {}
# 以root为根的最大值
def rob(self, root):
"""
:type root: TreeNode
:rtype: int
"""
if not root:
return 0
if root in self.rec:
return self.rec[root]
cur_val = root.val
if root.left:
cur_val += self.rob(root.left.left) + self.rob(root.left.right)
if root.right:
cur_val += self.rob(root.right.left) + self.rob(root.right.right)
self.rec[root] = max(cur_val, self.rob(root.left) + self.rob(root.right))
return self.rec[root]
class Solution(object):
def rob(self, root):
"""
:type root: TreeNode
:rtype: int
"""
if not root:
return 0
res = self.DFS(root)
return max(res[0], res[1])
# 返回:第一个表示不偷root的最大值,第二个表示偷root的最大值
def DFS(self, root):
if not root:
return [0, 0]
left_val = self.DFS(root.left)
right_val = self.DFS(root.right)
res = [0, 0]
res[0] = max(left_val) + max(right_val)
res[1] = left_val[0] + right_val[0] + root.val
return res
144. 二叉树的前序遍历
https://leetcode-cn.com/problems/binary-tree-preorder-traversal/
题解
一:递归,二叉树遍历,左子树一定在右子树之前,前中后说的是根节点的访问顺序。前序遍历:根->左->右。
class Solution(object):
def preorderTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
res = []
if not root:
return res
res.append(root.val)
res.extend(self.preorderTraversal(root.left))
res.extend(self.preorderTraversal(root.right))
return res
二:迭代,借助栈的结构,先进后出。每次往q的末尾加入元素,也从末尾弹出元素。visit指令表示经过该节点并压栈,add指令表示遍历该节点即将其加入res列表中。else结构中的顺序与遍历顺序(根->左->右)刚好相反。
class Solution(object):
def preorderTraversal(self, root):
stack, ans = [], []
if not root:
return ans
stack.append((root, "visited"))
while stack:
node, command = stack.pop()
if command == 'add':
ans.append(node.val)
else:
if node.right:
stack.append((node.right, "visited"))
if node.left:
stack.append((node.left, "visited"))
stack.append((node, 'add'))
return ans
class Solution(object):
def preorderTraversal(self, root):
stack, ans = [], []
if not root:
return ans
stack.append(root)
while stack:
node = stack.pop()
ans += [node.val]
if node.right:
stack.append(node.right)
if node.left:
stack.append(node.left)
return ans
94. 二叉树的中序遍历
https://leetcode-cn.com/problems/binary-tree-inorder-traversal/
题解
一:递归,中序遍历:左->根->右。
class Solution(object):
def inorderTraversal(self, root):
ans = []
if not root:
return ans
if root.left:
ans += self.inorderTraversal(root.left)
ans += [root.val]
if root.right:
ans += self.inorderTraversal(root.right)
return ans
二:迭代,else结构中的顺序与遍历顺序(左->根->右)刚好相反。
class Solution(object):
def inorderTraversal(self, root):
ans, stack = [], []
if not root:
return ans
stack.append((root, 'visited'))
while stack:
node, command = stack.pop()
if command == 'add':
ans.append(node.val)
else:
if node.right:
stack.append((node.right, 'visited'))
stack.append((node, 'add'))
if node.left:
stack.append((node.left, 'visited'))
return ans
145. 二叉树的后序遍历
https://leetcode-cn.com/problems/binary-tree-postorder-traversal/
题解
一:递归,后序遍历:左->右->根。
class Solution(object):
def postorderTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
res = []
if not root:
return res
res.extend(self.postorderTraversal(root.left))
res.extend(self.postorderTraversal(root.right))
res.append(root.val)
return res
二::迭代,else结构中的顺序与遍历顺序(左->右->根)刚好相反。
from collections import deque
class Solution(object):
def postorderTraversal(self, root):
res, q = [], deque()
if not root:
return res
q.append((root, "visit"))
while q:
node, command = q.pop()
if command == "add":
res.append(node.val)
else:
q.append((node, "add"))
if node.right:
q.append((node.right, "visit"))
if node.left:
q.append((node.left, "visit"))
return res
589. N叉树的前序遍历
https://leetcode-cn.com/problems/n-ary-tree-preorder-traversal/
题解
一:递归,self.children中的children是一个列表,列表中的元素是该节点的子节点
"""
# Definition for a Node.
class Node(object):
def __init__(self, val=None, children=None):
self.val = val
self.children = children
"""
class Solution(object):
def preorder(self, root):
"""
:type root: Node
:rtype: List[int]
"""
res = []
if not root:
return res
res.append(root.val)
for children in root.children:
res += self.preorder(children)
return res
二:迭代,注意node.children[::-1]
from collections import deque
class Solution(object):
def preorder(self, root):
"""
:type root: Node
:rtype: List[int]
"""
res = []
if not root:
return res
q = deque()
q.append((root, "visit"))
while q:
node, command = q.pop()
if command == "add":
res.append(node.val)
else:
for child in node.children[::-1]:
q.append((child, "visit"))
q.append((node, "add"))
return res
590. N叉树的后序遍历
https://leetcode-cn.com/problems/n-ary-tree-postorder-traversal/
题解
一:递归
class Solution(object):
def postorder(self, root):
"""
:type root: Node
:rtype: List[int]
"""
res = []
if not root:
return res
for child in root.children:
res += self.postorder(child)
res += [root.val]
return res
二:迭代
from collections import deque
class Solution(object):
def postorder(self, root):
res = []
if not root:
return res
q = deque()
q.append((root, "visit"))
while q:
node, command = q.pop()
if command == "add":
res.append(node.val)
else:
q.append((node, "add"))
for child in node.children[::-1]:
q.append((child, "visit"))
return res
102. 二叉树的层序遍历
https://leetcode-cn.com/problems/binary-tree-level-order-traversal/
题解
一:借用队列结构,先进先出。
class Solution(object):
def levelOrder(self, root):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
if not root:
return []
q, res = deque(), []
q.append(root)
while q:
n = len(q)
res.append([])
for i in range(n):
node = q.popleft()
res[-1].append(node.val)
if node.left:
q.append(node.left)
if node.right:
q.append(node.right)
return res
559. N叉树的最大深度
https://leetcode-cn.com/problems/maximum-depth-of-n-ary-tree/
题解
一:递归,DFS
class Solution(object):
def maxDepth(self, root):
"""
:type root: Node
:rtype: int
"""
res = 0
if not root:
return res
for child in root.children:
res = max(res, self.maxDepth(child))
res += 1
return res
二:迭代,BFS,层序遍历
from collections import deque
class Solution(object):
def maxDepth(self, root):
if not root:
return 0
res, q = 0, deque()
q.append(root)
while q:
n = len(q)
for i in range(n):
node = q.popleft()
for child in node.children:
q.append(child)
res += 1
return res
1022. 从根到叶的二进制数之和
https://leetcode-cn.com/problems/sum-of-root-to-leaf-binary-numbers/
给出一棵二叉树,其上每个结点的值都是 0 或 1 。每一条从根到叶的路径都代表一个从最高有效位开始的二进制数。例如,如果路径为 0 -> 1 -> 1 -> 0 -> 1,那么它表示二进制数 01101,也就是 13 。对树上的每一片叶子,我们都要找出从根到该叶子的路径所表示的数字。
题解
一:借用层序遍历的思想,用队列先进先出的结构,队列中放入节点,以及截止该节点的二进制表示的十进制数(截止其父节点的数*2+当前节点的值)的pair对,当该节点是叶子节点,我们将该数加入结果。
from collections import deque
class Solution(object):
def sumRootToLeaf(self, root):
"""
:type root: TreeNode
:rtype: int
"""
if not root:
return 0
q, res = deque(), 0
q.append((root, root.val))
while q:
n = len(q)
for i in range(n):
node, v = q.popleft()
if not node.left and not node.right:
res += v
if node.left:
q.append((node.left, v * 2 + node.left.val))
if node.right:
q.append((node.right, v * 2 + node.right.val))
return res
二:DFS,递归,寻求递归关系,当前结点的二进制和=上一结点的二进制和*2+当前结点的值。
class Solution(object):
def sumRootToLeaf(self, root):
if not root:
return 0
return self.dfs(root, 0)
def dfs(self, root, val):
if not root:
return 0
val = 2 * val + root.val
if not root.left and not root.right:
return val
return self.dfs(root.left, val) + self.dfs(root.right, val)
538. 把二叉搜索树转换为累加树
https://leetcode-cn.com/problems/convert-bst-to-greater-tree/
题解
一:回溯,我们想办法在遍历一个节点之前先遍历完所有比他大的节点,这些节点存在于右子树中,故先遍历右子树,在遍历该节点,在遍历左子树(右->根->左),即从小到大遍历, 同时维护一个全局变量,用来记录累加和,这样遍历到一个节点,已经遍历过大于他的节点,将全局变量加上当前节点的值即是对应新的根节点的值。dfs返回的是符合题意的对应当前节点的新的根。
class Solution(object):
def __init__(self):
self.res = 0
def convertBST(self, root):
"""
:type root: TreeNode
:rtype: TreeNode
"""
def dfs(root):
if not root:
return None, self.res
new_root = TreeNode(0)
new_root.right = dfs(root.right)[0]
self.res += root.val
new_root.val = self.res
new_root.left = dfs(root.left)[0]
return new_root, self.res
if not root:
return None
new_root = dfs(root)[0]
return new_root