Background:
Tree Traversals (Inorder, Preorder and Postorder) - GeeksforGeeks
Unlike linear data structures (Array, Linked List, Queues, Stacks, etc) which have only one logical way to traverse them, trees can be traversed in different ways. Following are the generally used ways for traversing trees.
Example Tree
Depth First Traversals:
(a) Inorder (Left, Root, Right) : 4 2 5 1 3
(b) Preorder (Root, Left, Right) : 1 2 4 5 3
(c) Postorder (Left, Right, Root) : 4 5 2 3 1
Breadth First or Level Order Traversal : 1 2 3 4 5
Please see this post for Breadth First Traversal.
Inorder Traversal (Practice):中序
Algorithm Inorder(tree)
1. Traverse the left subtree, i.e., call Inorder(left-subtree)
2. Visit the root.
3. Traverse the right subtree, i.e., call Inorder(right-subtree)
Uses of Inorder
In case of binary search trees (BST), Inorder traversal gives nodes in non-decreasing order. To get nodes of BST in non-increasing order, a variation of Inorder traversal where Inorder traversal s reversed can be used.
Example: Inorder traversal for the above-given figure is 4 2 5 1 3.
Preorder Traversal (Practice):前序
Algorithm Preorder(tree)
1. Visit the root.
2. Traverse the left subtree, i.e., call Preorder(left-subtree)
3. Traverse the right subtree, i.e., call Preorder(right-subtree)
Uses of Preorder
Preorder traversal is used to create a copy of the tree. Preorder traversal is also used to get prefix expression on of an expression tree. Please see http://en.wikipedia.org/wiki/Polish_notation to know why prefix expressions are useful.
Example: Preorder traversal for the above given figure is 1 2 4 5 3.
Postorder Traversal (Practice):后序
Algorithm Postorder(tree)
1. Traverse the left subtree, i.e., call Postorder(left-subtree)
2. Traverse the right subtree, i.e., call Postorder(right-subtree)
3. Visit the root.
Uses of Postorder
Postorder traversal is used to delete the tree. Please see the question for deletion of tree for details. Postorder traversal is also useful to get the postfix expression of an expression tree. Please see http://en.wikipedia.org/wiki/Reverse_Polish_notation to for the usage of postfix expression.
==============================
1080. Insufficient Nodes in Root to Leaf Paths
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def sufficientSubset(self, root: Optional[TreeNode], limit: int) -> Optional[TreeNode]:
# 自己写的,题目的意思是,如果通过该点的所有从root到leaf的路径上的sum全部都小于limit 那么就删除
# 该点
def isSufficient(node, total):
# 到最leaf的节点再判断sum是不是小于limit 再把这个ture/false网上传
if not node.left and not node.right:
total += node.val
if total < limit:
return False
else:
return True
total += node.val
left_re = right_re = False
if node.left:
left_re = isSufficient(node.left, total)
if node.right:
right_re = isSufficient(node.right, total)
if not left_re:
node.left = None
if not right_re:
node.right = None
return left_re or right_re
return root if isSufficient(root, 0) else None # root可能也是非法的
331. Verify Preorder Serialization of a Binary Tree
class Solution(object):
def isValidSerialization(self, preorder):
"""
We just need to remember how many empty slots we have during the process.
Initially we have one ( for the root ).
for each node we check if we still have empty slots to put it in.
a null node occupies one slot.
a non-null node occupies one slot before he creates two more. the net gain is one.
"""
p = preorder.split(',')
#initially we have one empty slot to put the root in it
slot = 1
for node in p:
# no empty slot to put the current node
if slot == 0:
return False
# a null node?
if node == '#':
# ocuppy slot
slot -= 1
else:
# create new slot
slot += 1
#we don't allow empty slots at the end
return slot==0
1026. Maximum Difference Between Node and Ancestor
class Solution:
def maxAncestorDiff(self, root: Optional[TreeNode]) -> int:
# find bigest and smallest values from left and right
self.re = 0
def dfs(node):
if not node:
return None, None
lmin, lmax = dfs(node.left)
rmin, rmax = dfs(node.right)
cur = node.val
l = r = cur
for v in (lmin, lmax, rmin, rmax):
if v != None:
self.re = max(self.re, abs(cur - v))
l = min(l, v)
r = max(r, v)
return l, r
dfs(root)
return self.re
1325. Delete Leaves With a Given Value
class Solution:
def removeLeafNodes(self, root: Optional[TreeNode], target: int):
# O(N) solution with DFS
def dfs(node):
if not node:
return None
if node.val == target and not node.left and not node.right:
return None
node.left = dfs(node.left)
node.right = dfs(node.right)
if node.val == target and not node.left and not node.right:
return None
return node
return dfs(root)
# 下面是自己写的
# root, _ = self.remove(root, target)
# return root
# def remove(self, root: Optional[TreeNode], target: int):
# left, right = None, None
# if root.left:
# left, shouldDel = self.remove(root.left, target)
# if shouldDel:
# root.left = None
# if root.right:
# right, shouldDel = self.remove(root.right, target)
# if shouldDel:
# root.right = None
# if left == right == None and root.val == target:
# return None, True
# return root, False
894. All Possible Full Binary Trees
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def allPossibleFBT(self, n: int) -> List[Optional[TreeNode]]:
if not n or not n % 2: # 如果是偶数个的就没必要继续了,因为不会是full binrary tree
return []
if n == 1:
return [TreeNode()]
res = []
for i in range(1, n-1, 2): # 奇数
lefts = self.allPossibleFBT(i)
rights = self.allPossibleFBT(n-1-i)
for left in lefts:
for right in rights:
root = TreeNode(0, left, right)
res.append(root)
return res
814. Binary Tree Pruning
class Solution:
def pruneTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
# Bottom up
def dfs(node):
if not node:
return 0 # 0 means this node can be deleted
left = dfs(node.left)
right = dfs(node.right)
if left == 0:
node.left = None # delete the node
if right == 0:
node.right = None # delete the node
if left == right == node.val == 0: # left and right can be deleted and cur node.val = 0 means it can be deleted
return 0
return 1 # cannot be deleted
return None if dfs(root) == 0 else root # edge case to delete root
# 答案的写法:
'''
if not root: return None
root.left = self.pruneTree(root.left)
root.right = self.pruneTree(root.right)
if not root.left and not root.right and not root.val: return None
return root
'''
1650. Lowest Common Ancestor of a Binary Tree III
class Solution:
def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':
# 类似于 linkedlist 快慢指针
'''
For anyone struggling to see it, imagine to nodes, p and q, whose paths merge and become common after a certain number of steps.
p1 -> p2 -> p3 -> c1 -> c2 -> c3
q1 -> q2 -> q3 -> c1 -> c2 -> c3
If the distance from p1 to c1 is the same as the distance from q1 to c1, it's pretty obvious this algorithm will find when c1 == c1.
But now imagine those distances are different.
p1 -> p2 -> p3 -> c1 -> c2 -> c3
.........................q1 -> c1 -> c2 -> c3
If you force them to switch paths after they reach c3:
P Travels: (3 steps to c1), (3 common steps to q1), (1 step to c1)
Q Travels: (1 step to c1), (3 common steps to p1), (3 steps to c1)
OR put another way
P Travels: PC, C, QC
Q Travels: QC, C, PC
where C is the common paths. PC is p's unique path to the common ancestor. QC is q's unique path.
'''
p1, p2 = p, q
while p1 != p2:
p1 = p1.parent if p1.parent else q
p2 = p2.parent if p2.parent else p
return p1
1373. Maximum Sum BST in Binary Tree
class Solution:
def maxSumBST(self, root: Optional[TreeNode]) -> int:
# 不同于 https://leetcode.com/problems/validate-binary-search-tree/ 两个largerThan, smallThan 是从上传到下面, 这题需要这2个值从下往上传
# O(n) Time complexity
self.re = 0
def isValidBST(node):
if not node:
return True, 0, float('inf'), float('-inf') # isBST, sum of BST, minVal in BST, maxVal in BST, 后面这两个float 是根据line 20写出来的
left, sum_left, minLV, maxLV = isValidBST(node.left)
right, sum_right, minRV, maxRV = isValidBST(node.right)
if left and right and node.val > maxLV and node.val < minRV:
total = node.val + sum_left + sum_right
self.re = max(self.re, total)
return True, total, min(node.val, minLV), max(maxRV, node.val)
return False, 0, -1, -1 # when false, we don't care the max_val, min_val
isValidBST(root)
return self.re
968. Binary Tree Cameras
class Solution:
def minCameraCover(self, root: Optional[TreeNode]) -> int:
# 从叶子节点开始向上
# 空节点返回-1 表示没有,也不需要被上层cover
# 返回0 表示当前没有, 需要被cover
# 返回1, 表示当前有, 可以cover上面 (子节点有一个一定需要被cover)
# 返回-1 表示当前没有,也不需要被上面cover # 这个可以直接返回-1
self.res = 0
def dfs(node):
if not node: # 空节点,
return -1
l, r = dfs(node.left), dfs(node.right)
if 0 in [l, r]: # 子节点有一个需要被cover
self.res += 1
return 1
if l == 1 or r == 1: # 当前没有,也不需要被cover
return -1
return 0
dfs(root)
return self.res + (dfs(root) == 0) # edge case: root 节点的左右两边都是空的, 也不需要被cover, 这时候root节点还是需要有个摄像头
95. Unique Binary Search Trees II
class Solution(object):
def generateTrees(self, n):
"""
:type n: int
:rtype: List[TreeNode]
"""
def generate_trees(start, end):
if start > end:
return [None]
allTrees = []
for i in xrange(start, end+1): # pick an element as root between start to end
leftTrees = generate_trees(start, i-1)
rightTrees = generate_trees(i+1, end)
# combine left root right
for left in leftTrees:
for right in rightTrees:
root = TreeNode(i) # 这个不能写在上面
root.left = left
root.right = right
allTrees.append(root)
return allTrees
return generate_trees(1, n) if n else []
617. Merge Two Binary Trees
class Solution(object):
def mergeTrees(self, t1, t2):
if not t1 and not t2: return None
res = TreeNode(0)
res.val = (t1.val if t1 else 0) + (t2.val if t2 else 0)
res.left = self.mergeTrees(t1 and t1.left, t2 and t2.left)
res.right = self.mergeTrees(t1 and t1.right, t2 and t2.right)
return res
103. Binary Tree Zigzag Level Order Traversal
class Solution(object):
def zigzagLevelOrder(self, root):
if not root: return []
level = [root]
re = []
flag = 1
while level:
Next = []
temp = []
while level:
node = level.pop(0)
temp.append(node.val)
if node.left: Next.append(node.left)
if node.right: Next.append(node.right)
level = Next
re.append(temp[::flag])
flag *= -1
return re
437. Path Sum III
class Solution(object):
def pathSum(self, root, sum):
if not root: return 0
return self.getSumFrom(root, sum) + self.pathSum(root.left, sum) + self.pathSum(root.right, sum)
def getSumFrom(self, node, s):
if not node:
return 0
cur = 0
if node.val == s:
cur += 1
return cur + self.getSumFrom(node.left, s-node.val) + self.getSumFrom(node.right, s-node.val)
222. Count Complete Tree Nodes
it needs to find the depth for its left and right child, which is log(n), and then it needs to run countNodes for its left child or right child which is another log(n), so it's log(n) * log(n).
class Solution(object):
def countNodes(self, root):
if not root: return 0
leftDepth = self.getDepth(root.left)
rightDepth = self.getDepth(root.right)
if leftDepth == rightDepth: # left is full binary tree
return 2**leftDepth + self.countNodes(root.right)
else:
# leftDepth > rightDepth right is a full binary tree
return 2**rightDepth + self.countNodes(root.left)
def getDepth(self, node):
if not node: return 0
return self.getDepth(node.left) + 1
333. Largest BST Subtree
class Solution(object):
def largestBSTSubtree(self, root):
self.re = 0
def find(node):
if not node: return float('inf'), float('-inf'), 0
lmin, lmax, lnum = find(node.left)
rmin, rmax, rnum = find(node.right)
n = float('-inf')
if node.val > lmax and node.val < rmin:
n = lnum + rnum + 1
self.re = max(n, self.re)
return min(node.val, lmin), max(node.val, rmax), n
find(root)
return self.re
450. Delete Node in a BST
class Solution(object):
def deleteNode(self, root, key):
if not root: return None
if key > root.val:
root.right = self.deleteNode(root.right, key)
elif key < root.val:
root.left = self.deleteNode(root.left, key)
else:
if not root.left:
return root.right
if not root.right:
return root.left
right = root.right
left = root.left
temp = right
while temp.left:
temp = temp.left
temp.left = left
root = right
return root
655. Print Binary Tree
class Solution(object):
def printTree(self, root):
def height(root):
if not root: return 0
left = height(root.left)
right = height(root.right)
return max(left, right) + 1
high = height(root)
width = 2**high - 1
res = [[''] *width for _ in xrange(high)]
def update(i, j, level, node, res):
if not node: return
mid = (i+j) / 2
res[level][mid] = str(node.val)
update(i, mid-1, level+1, node.left, res)
update(mid+1, j, level+1, node.right, res)
update(0, width-1, 0, root, res)
return res
979. Distribute Coins in Binary Tree
子节点需要几个,和子节点多出几个,加起来。
class Solution(object):
res = 0
def distributeCoins(self, root):
def dfs(node):
if not node: return 0
left = dfs(node.left)
right = dfs(node.right)
self.res += abs(left) + abs(right) # 这里有绝对值
return node.val + left + right - 1
dfs(root)
return self.res
662. Maximum Width of Binary Tree
If the index of a node is i
, the indices of its two children are 2*i
and 2*i + 1
.
class Solution(object):
def widthOfBinaryTree(self, root):
if not root: return 0
level = [(root, 1)]
w = 1
while level:
next = []
for node, ids in level:
if node.left: next.append((node.left, ids*2))
if node.right: next.append((node.right, ids*2+1))
w = max(w, level[-1][1]-level[0][1]+1)
level = next
return w
366. Find Leaves of Binary Tree
class Solution(object):
def findLeaves(self, root):
d = collections.defaultdict(list)
def height(node):
if not node: return -1
left = height(node.left)
right = height(node.right)
h = max(left, right) + 1
d[h].append(node.val)
return h
high = height(root)
res = []
for i in xrange(high+1):
res.append(d[i])
return res
865. Smallest Subtree with all the Deepest Nodes
class Solution(object):
def subtreeWithAllDeepest(self, root):
# one pass
def deep(root):
if not root: return None, 0
left, ldeep = deep(root.left)
right, rdeep = deep(root.right)
if ldeep > rdeep:
return left, ldeep + 1
elif ldeep < rdeep:
return right, rdeep + 1
else:
return root, ldeep+1
return deep(root)[0]
958. Check Completeness of a Binary Tree
新的level by level的方法,用i来控制,就不需要nextLevel了
class Solution(object):
def isCompleteTree(self, root):
level = [root]
i = 0
while level[i]:
node = level[i]
level.append(node.left)
level.append(node.right)
i += 1
return not any(level[i:])
536. Construct Binary Tree from String
class Solution(object):
def str2tree(self, s):
left = s.find('(') # 第一个左括号的Idx
if left < 0:
return TreeNode(int(s)) if s else None
p = 0
for i, c in enumerate(s):
if c == '(': p += 1
elif c == ')': p -= 1
if p == 0 and i > left: break
root = TreeNode(int(s[:left]))
root.left = self.str2tree(s[left+1:i])
root.right = self.str2tree(s[i+2:-1]) # 注意这里+2, 和-1 最后一个)是不要的
return root
617. Merge Two Binary Trees
class Solution(object):
def mergeTrees(self, t1, t2):
if t1 and t2:
root = TreeNode(t1.val+t2.val)
root.left = self.mergeTrees(t1.left, t2.left)
root.right = self.mergeTrees(t1.right, t2.right)
return root
else:
return t1 or t2
545. Boundary of Binary Tree
class Solution(object):
def boundaryOfBinaryTree(self, root):
def dfs_leftmost(node): # preorder
if not node or not node.left and not node.right:
return
re.append(node.val)
if node.left:
dfs_leftmost(node.left)
else:
dfs_leftmost(node.right)
def dfs_leaves(node): # inorder
if not node:
return
dfs_leaves(node.left)
if node != root and not node.left and not node.right:
re.append(node.val)
dfs_leaves(node.right)
def dfs_rightmost(node): # postorder
if not node or not node.left and not node.right:
return
if node.right:
dfs_rightmost(node.right)
else:
dfs_rightmost(node.left)
re.append(node.val)
if not root:
return []
re = [root.val]
dfs_leftmost(root.left)
dfs_leaves(root)
dfs_rightmost(root.right)
return re
235. Lowest Common Ancestor of a Binary Search Tree
class Solution(object):
def lowestCommonAncestor(self, root, p, q):
"""
:type root: TreeNode
:type p: TreeNode
:type q: TreeNode
:rtype: TreeNode
"""
while root:
if root.val > p.val and root.val > q.val:
root = root.left
elif root.val < p.val and root.val < q.val:
root = root.right
else:
return root
105. Construct Binary Tree from Preorder and Inorder Traversal
Given preorder and inorder traversal of a tree, construct the binary tree.
Note:
You may assume that duplicates do not exist in the tree.
For example, given
preorder = [3,9,20,15,7]
inorder = [9,3,15,20,7]
Return the following binary tree:
3
/ \
9 20
/ \
15 7
# 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 buildTree(self, preorder, inorder):
"""
:type preorder: List[int]
:type inorder: List[int]
:rtype: TreeNode
"""
if inorder:
ind = inorder.index(preorder.pop(0))
root = TreeNode(inorder[ind])
root.left = self.buildTree(preorder, inorder[0: ind])
root.right = self.buildTree(preorder, inorder[ind+1:])
return root
106. Construct Binary Tree from Inorder and Postorder Traversal
Given inorder and postorder traversal of a tree, construct the binary tree.
Note:
You may assume that duplicates do not exist in the tree.
For example, given
inorder = [9,3,15,20,7]
postorder = [9,15,7,20,3]
Return the following binary tree:
3
/ \
9 20
/ \
15 7
class Solution(object):
def buildTree(self, inorder, postorder):
"""
:type inorder: List[int]
:type postorder: List[int]
:rtype: TreeNode
"""
if not postorder or not inorder:
return
root = TreeNode(postorder.pop())
inorderIndex = inorder.index(root.val)
root.right = self.buildTree(inorder[inorderIndex+1:], postorder)
root.left = self.buildTree(inorder[:inorderIndex], postorder)
return root
230. Kth Smallest Element in a BST
递归访问左节点->自己->右节点
class Solution(object):
def kthSmallest(self, root, k):
"""
:type root: TreeNode
:type k: int
:rtype: int
"""
self.count = self.result = 0
self.helper(root, k)
return self.result
def helper(self, root, k):
if not root:
return
self.helper(root.left, k)
self.count += 1
if self.count == k:
self.result = root.val
return
self.helper(root.right, k)
94. Binary Tree Inorder Traversal
inorder preorder的可以整理一下
class Solution(object):
def inorderTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
if root is None:
return []
return self.inorderTraversal(root.left) + [root.val] + self.inorderTraversal(root.right)
236. Lowest Common Ancestor of a Binary Tree
class Solution(object):
def lowestCommonAncestor(self, root, p, q):
"""
:type root: TreeNode
:type p: TreeNode
:type q: TreeNode
:rtype: TreeNode
"""
stack = [root]
parent = {root: None}
while p not in parent or q not in parent:
node = stack.pop()
if node.left:
parent[node.left] = node
stack.append(node.left)
if node.right:
parent[node.right] = node
stack.append(node.right)
ancestors = set()
while p:
ancestors.add(p)
p = parent[p]
while q not in ancestors:
q = parent[q]
return q
1644. Lowest Common Ancestor of a Binary Tree II
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
'''
different with 236. Last Common Ancestor of Binary Tree, p q 是有可能不存在的,所以不能找到p或者q的时候就返回了,而是要继续遍历整颗树
'''
self.p = False # find p?
self.q = False # find q?
def lca(node, p, q):
if not node:
return None
left = lca(node.left, p, q) # 这两个left right会保证一直dfs 进去
right = lca(node.right, p, q)
if node == p:
self.p = True
return node
if node == q:
self.q = True
return node
if left and right:
return node
return left or right
node = lca(root, p, q)
return node if self.p and self.q else None
102. Binary Tree Level Order Traversal
medium但是太多同类型的了所以很简单
class Solution(object):
def levelOrder(self, root):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
q = [root] if root else []
re = []
while q:
cur = [node.val for node in q]
re.append(cur)
q = [n for node in q for n in (node.left, node.right) if n]
return re
297. Serialize and Deserialize Binary Tree
449. Serialize and Deserialize BST
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Codec:
def serialize(self, root):
if not root: return '#'
preorder = str(root.val)
left = self.serialize(root.left)
right = self.serialize(root.right)
return ".".join([preorder, left, right])
def deserialize(self, data):
# print(data)
nodes = data.split(".")
self.i = 0
def dfs():
if self.i == len(nodes):
return None
v = nodes[self.i]
self.i += 1
if v == '#':
return None
root = TreeNode(int(v))
root.left = dfs()
root.right = dfs()
return root
return dfs()
428. Serialize and Deserialize N-ary Tree
"""
# Definition for a Node.
class Node(object):
def __init__(self, val: Optional[int] = None, children: Optional[List['Node']] = None):
if children is None:
children = []
self.val = val
self.children = children
"""
class Codec:
def serialize(self, root: 'Node') -> str:
s = []
def preorder(node):
if not node:
return
s.append(str(node.val))
for child in node.children:
preorder(child)
s.append('#') # indicates no more child
preorder(root)
# 每个字符都是用.链接起来
return ".".join(s)
def deserialize(self, data: str) -> 'Node':
# print(data)
if not data:
return None
s = deque(data.split('.'))
root = Node(int(s.popleft()))
def helper(node):
if not s:
return
while s[0] != '#':
v = int(s.popleft())
child = Node(v)
node.children.append(child)
helper(child)
s.popleft() # discard #
helper(root)
return root
572. Subtree of Another Tree
思路:检查左边再检查右边子树。没有看答案一次过。
class Solution(object):
def isSubtree(self, s, t):
"""
:type s: TreeNode
:type t: TreeNode
:rtype: bool
"""
stack = [s]
while stack:
node = stack.pop()
if node.val == t.val and self.check(node, t):
return True
if node.left:
stack.append(node.left)
if node.right:
stack.append(node.right)
return False
def check(self, s1, t1):
# check the tree is the same or not
if s1 and t1 and s1.val == t1.val:
if self.check(s1.left, t1.left) and self.check(s1.right, t1.right):
return True
if s1 is None and t1 is None:
return True
426. Convert Binary Search Tree to Sorted Doubly Linked List
Convert a BST to a sorted circular doubly-linked list in-place. Think of the left and right pointers as synonymous to the previous and next pointers in a doubly-linked list.
Let's take the following BST as an example, it may help you understand the problem better:
We want to transform this BST into a circular doubly linked list. Each node in a doubly linked list has a predecessor and successor. For a circular doubly linked list, the predecessor of the first element is the last element, and the successor of the last element is the first element.
The figure below shows the circular doubly linked list for the BST above. The "head" symbol means the node it points to is the smallest element of the linked list.
Specifically, we want to do the transformation in place. After the transformation, the left pointer of the tree node should point to its predecessor, and the right pointer should point to its successor. We should return the pointer to the first element of the linked list.
The figure below shows the transformed BST. The solid line indicates the successor relationship, while the dashed line means the predecessor relationship.
思路:
241
Step 1: Divide:
We divide tree into three parts: left subtree, root node, right subtree.
Convert left subtree into a circular doubly linked list as well as the right subtree.
Be careful. You have to make the root node become a circular doubly linked list.
Step 2: Conquer:
Firstly, connect left circular doubly linked list with the root circular doubly linked list.
Secondly, connect them with the right circular doubly linked list. Here we go!
"""
# Definition for a Node.
class Node(object):
def __init__(self, val, left, right):
self.val = val
self.left = left
self.right = right
"""
class Solution(object):
def treeToDoublyList(self, root):
"""
:type root: Node
:rtype: Node
"""
if not root:
return
leftHead = self.treeToDoublyList(root.left)
rightHead = self.treeToDoublyList(root.right)
root.left = root
root.right = root
return self.connect(self.connect(leftHead, root), rightHead)
def connect(self, n1, n2):
if not n1:
return n2
if not n2:
return n1
tail1 = n1.left # 左边的最后一个即head的前一个
tail2 = n2.left # 右边的最后一个同理
tail1.right = n2
n2.left = tail1
tail2.right = n1
n1.left = tail2
return n1
124. Binary Tree Maximum Path Sum
class Solution(object):
def maxPathSum(self, root):
# left max + right max + cur node
self.res = float('-inf')
def maxPath(root):
if not root:
return 0
left = max(0, maxPath(root.left))
right = max(0, maxPath(root.right))
self.res = max(self.res, left+right+root.val)
return max(left, right) + root.val # 注意这里只能是 左边或者右边的path加当前节点
maxPath(root)
return self.res
543. Diameter of Binary Tree
和上题几乎一样
class Solution(object):
def diameterOfBinaryTree(self, root):
"""
:type root: TreeNode
:rtype: int
"""
self.re = 0
self.pathDown(root)
return self. re
def pathDown(self, node):
if not node:
return 0
left = self.pathDown(node.left)
right = self.pathDown(node.right)
self.re = max(self.re, left + right)
return max(left, right) + 1
314. Binary Tree Vertical Order Traversal
Given a binary tree, return the vertical order traversal of its nodes' values. (ie, from top to bottom, column by column).
If two nodes are in the same row and column, the order should be from left to right.
class Solution(object):
def verticalOrder(self, root):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
cols = collections.defaultdict(list)
queue = [(root, 0)]
while queue:
node, col = queue.pop(0)
if node:
cols[col].append(node.val)
queue.append((node.left, col-1))
queue.append((node.right, col+1))
return [cols[i] for i in sorted(cols)]
99. Recover Binary Search Tree
这种格式的是按照inorder顺序来的:
根据inorder 比较时候,当前节点在左时候(preNode)比curNode(父节点)小, 当前节点(preNode)在父节点的时候:比右子树 最左的节点小
class Solution(object):
def recoverTree(self, root):
"""
:type root: TreeNode
:rtype: void Do not return anything, modify root in-place instead.
"""
self.firstNode = None
self.secondNode = None
self.preNode = TreeNode(float('-inf'))
self.traverse(root)
self.firstNode.val, self.secondNode.val = self.secondNode.val, self.firstNode.val
def traverse(self, node):
if not node:
return
self.traverse(node.left)
if self.firstNode == None and self.preNode.val >= node.val:
self.firstNode = self.preNode
if self.firstNode and self.preNode.val >= node.val:
self.secondNode = node
self.preNode = node
self.traverse(node.right)
285. Inorder Successor in BST
自己写的很长,但是OJ accept了。懒得研究为什么别人的那么短了。
class Solution(object):
def inorderSuccessor(self, root, p):
"""
:type root: TreeNode
:type p: TreeNode
:rtype: TreeNode
"""
if not root:
return None
self.find = False
return self.helper(root, p.val)
def helper(self, node, val):
if not node:
return
left = self.helper(node.left, val)
if left: return left
if self.find:
return node
if node.val == val:
self.find = True
right = self.helper(node.right, val)
if right: return right
652. Find Duplicate Subtrees
O(n) O(n)
class Solution(object):
def findDuplicateSubtrees(self, root):
"""
:type root: TreeNode
:rtype: List[TreeNode]
"""
self.type_id_gen = 0
type_to_freq = collections.defaultdict(int)
type_to_id = {}
duplicate = []
def dfs(node):
if not node:
return -1
type_id_left, type_id_right = dfs(node.left), dfs(node.right)
tree_type = (node.val, type_id_left, type_id_right)
print tree_type
freq = type_to_freq[tree_type]
if freq == 0:
type_id = self.type_id_gen
type_to_id[tree_type] = self.type_id_gen
self.type_id_gen += 1
elif freq == 1:
type_id = type_to_id[tree_type]
duplicate.append(node)
else:
type_id = type_to_id[tree_type]
type_to_freq[tree_type] += 1
return type_id
dfs(root)
return duplicate
def findDuplicateSubtrees(self, root, heights=[]):
def getid(root):
if root:
id = treeid[root.val, getid(root.left), getid(root.right)]
trees[id].append(root)
return id
trees = collections.defaultdict(list)
treeid = collections.defaultdict()
treeid.default_factory = treeid.__len__
getid(root)
return [roots[0] for roots in trees.values() if roots[1:]]
783. Minimum Distance Between BST Nodes
经典Inorder
class Solution(object):
def minDiffInBST(self, root):
"""
:type root: TreeNode
:rtype: int
"""
self.re = float('inf')
self.preNode = float('-inf')
def inorder(node):
if not node:
return
inorder(node.left)
self.re = min(self.re, abs(node.val - self.preNode))
self.preNode = node.val
inorder(node.right)
inorder(root)
return self.re