好处是有很好的locality,可以很简单的用array等物理连续的存储 做level order traversal时有紧凑的表示
Left Child Node Index = Parent Node Index * 2 +1 Right Child Node Index = Parent Node Index * 2 +2
Binary Search Tree
每一个node的左子树的所有node值比node小,右子树的所有值比node大
好处1是in-order print时是ascending order
好处2是方便查找,binary search似的,知道search的时候该往左还是往右
也可以存duplicated value
Bottom Up (从下往上返值 灵魂三问)
what do we expect from the left child/ right child?
what do you want to do in the current layer?
what do you want to return to your parent (same as 1)
Best Case: 假如input不是balanced,极端情况是两个linked list,此时的recursion tree是一叉树,时间复杂度是O(n)
Tweaked Identical Binary Trees
Invert a Binary Tree
Binary Tree Upside Down
Base Case不是None的例子
Given a binary tree where all the right nodes are either leaf nodes with a sibling (a left node that shares the same parent node) or empty, flip it upside down and turn it into a tree where the original right nodes turned into left leaf nodes. Return the new root.
面试题目 Suppose a tree is stored on the disk, and each node may have a large number of fan-out. We only have limited size of memory. How can we access the tree in level order?
用preorder traversal模拟level order 假设root是2,在level=1的时候打印。
再followup 如果来回从左到右-从右到左,zigzag打印?
——必须用2个queue,再加一个层数的变量
Get Keys In Binary Tree Layer By Layer Zig-Zag Order
Top Down (从上往下传值)
参数传递信息,用全局变量记录结果
通常不需要返值
思维更简单,但代码不如bottom up简洁
如果需要输出完整path,top down更实用 但是如果依赖subtree的结果,用bottom up
如果我们认为bottom up是post-order,那么top down就可以认为是preorder 即先做完自己这层的事情再做children的
def pre_order(root):
if not root:
return
print(root.val)
pre_order(root.left)
pre_order(root.right)
class Solution(object):
def preOrder(self, root):
"""
input: TreeNode root
return: Integer[]
"""
# write your solution here
result = []
self.helper(root,result)
return result
def helper(self, root, result):
if not root:
return result
result.append(root.val)
self.helper(root.left, result)
self.helper(root.right, result)
class Solution(object):
def inOrder(self, root):
"""
input: TreeNode root
return: Integer[]
"""
# write your solution here
result = []
self.helper(root, result)
return result
def helper(self, root, result):
if not root:
return result
self.helper(root.left, result)
result.append(root.val)
self.helper(root.right, result)
class Solution(object):
def postOrder(self, root):
"""
input: TreeNode root
return: Integer[]
"""
# write your solution here
result = []
self.helper(root,result)
return result
def helper(self, root, result):
if not root:
return result
self.helper(root.left, result)
self.helper(root.right, result)
result.append(root.val)
class Solution(object):
def findHeight(self, root):
"""
input: TreeNode root
return: int
"""
# write your solution here
if not root:
return 0
left = self.findHeight(root.left)
right = self.findHeight(root.right)
return max(left, right)+1
def get_size(root):
if not root:
return 0
left=get_size(root.left)
right=get_size(root.right)
return left+right+1
def get_value(root):
if not root:
return
left=get_value(root.left)
right=get_value(root.right)
return left+right+root.value
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
self.total_left = 0
def total_left(self, node)
if not node:
return
left_total=get_value(node.left)
right_total=get_value(node.right)
node.total_left = left_total # functionality
return left+right+1 # tell parent
global_max = -1 #因为None 和 一个节点是两种情况 这就做了区分
res = None
def node_diff(root):
if root is None:
return 0
left_total = node_diff(root.left)
right_total = node_diff(root.right)
global global_max
global res
if abs(left_total - right_total)>global_max:
global_max = abs(left_total - right_total)
res = root
return left_total+right_total+1
def get_max_dif(root):
global global_max
global res
node_diff(root)
return res
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class ResultWrapper:
def __init__(self):
self.global_max = -1
self.solution = None
def max_diff_node(root, res):
if not root:
return 0
left_total = max_diff_node(root.left, res)
right_total = max_diff_node(root.right, res)
if abs(left_total-right_total)>res.global_max:
res.global_max = abs(left_total - right_total)
res.solution = root
return left_total+right_total+1
def max_diff(root):
res = ResultWrapper() #生成object/instance
max_diff_node(root, res)
return res.solution
def minDepth(root):
if not root:
return 0
if root.left is None and root.right is None:
return 1
left = minDepth(root.left) if root.left else float('inf')
right = minDepth(root.right) if root.right else float('inf')
return min(left, right) + 1
def minDepth(root):
# Corner Case. Should never be hit unless the code is
# called on root = NULL
if root is None:
return 0
# Base Case : Leaf node.This acoounts for height = 1
if root.left is None and root.right is None:
return 1
# If left subtree is Null, recur for right subtree
if root.left is None:
return minDepth(root.right)+1
# If right subtree is Null , recur for left subtree
if root.right is None:
return minDepth(root.left) +1
return min(minDepth(root.left), minDepth(root.right))+1
def longest(curr, parent, currlen):
if not curr:
return currlen
size = 1
if parent and curr.val == parent.val+1
size = currlen+1
return max(currlen, longest(curr.left, curr, size), longest(curr.right, curr, size))
longest(root, None, 0)
class Solution (object):
def lowestCommonAncestor(self, root, p, q):
if not root:
return root
if root==p or root==q:
return root
ltree = self.lowestCommonAncestor(root.left, p, q)
rtree = self.lowestCommonAncestor(root.right, p, q)
if ltree and rtree:
return root
elif not ltree:
return rtree
else:
return ltree
class Solution(object):
def isBalanced(self, root):
"""
input: TreeNode root
return: boolean
"""
# write your solution here
if not root:
return True
left = self.getheight(root.left)
right = self.getheight(root.right)
if abs(left-right)>1:
return False
return self.isBalanced(root.left) and self.isBalanced(root.right)
def getheight(self, root):
if not root:
return 0
left = self.getheight(root.left)
right = self.getheight(root.right)
return max(left, right)+1
class Solution (object):
def isBalanced(self, root):
if self.helper(root) == -1
return False
else:
return True
def helper(self, root):
if not root:
return 0
left=self.get_height(root.left)
right=self.get_height(root.right)
if left==-1 or right==-1:
return -1
elif abs(left-right)>1:
return -1
else:
return max(left, right)+1
class Solution(object):
def isSymmetric(self, root):
"""
input: TreeNode root
return: boolean
"""
# write your solution here
if not root:
return True
return self.helper(root.left, root.right)
def helper(self, left, right):
if not left and not right:
return True
elif not left or not right:
return False
elif left.val!=right.val:
return False
return self.helper(left.left, right.right) and self.helper(left.right, right.left)
class Solution(object):
def isTweakedIdentical(self, one, two):
"""
input: TreeNode one, TreeNode two
return: boolean
"""
# write your solution here
if not one and not two:
return True
elif not one or not two:
return False
elif one.val!=two.val:
return False
return (self.isTweakedIdentical(one.left, two.left) and self.isTweakedIdentical(one.right, two.right)) or (self.isTweakedIdentical(one.left, two.right) and self.isTweakedIdentical(one.right, two.left))
class Solution:
def invertTree(self, root):
if root is None:
return None
if root.left:
self.invertTree(root.left)
if root.right:
self.invertTree(root.right)
root.left, root.right = root.right, root.left
return root
class Solution(object):
def invertTree(self, root):
"""
input: TreeNode root
return: TreeNode
"""
# write your solution here
if not root:
return root
leftres = root.left
root.left = self.invertTree(root.right)
root.right = self.invertTree(leftres)
return root
def upside_tree(root):
if not root:
return root
if not root.left and not root.right:
return root
left_tree = upside_tree(root.left)
root.left.left = root.right #根的右孩子变成了左孩子的左孩子
root.left.right = root #根变成了左孩子的右孩子
root.left = None
root.right = None
return left_tree
class Solution(object):
def reverse(self, root):
"""
input: TreeNode root
return: TreeNode
"""
# write your solution here
if not root:
return root
if not root.left and not root.right:
return root
newroot=self.reverse(root.left)
root.left.right=root.right
root.left.left=root
root.left = None
root.right = None
return newroot
class Solution(object):
def diameter(self, root):
"""
input: TreeNode root
return: int
"""
# write your solution here
self.maxnumber = 0
self.helper(root)
return self.maxnumber
def helper(self, root):
if not root:
return 0
left = self.helper(root.left)
right = self.helper(root.right)
if left>0 and right>0:
self.maxnumber = max(self.maxnumber, left+right+1)
return max(left, right) +1
def preorder_traversal(root):
output=[]
if not root:
return output
stack =[(root,1)]
while stack:
node, count = stack.pop()
if count == 1:
output.append(node.val)
stack.append((node, count+1))
if node.left:
stack.append((node.left, 1))
if count ==2:
if node.right:
stack.append((node.right,1))
return output
class Solution(object):
def preOrder(self, root):
"""
input: TreeNode root
return: Integer[]
"""
# write your solution here
result = []
if not root:
return result
line = [root]
while line:
curr = line.pop()
if curr.right:
line.append(curr.right)
if curr.left:
line.append(curr.left)
result.append(curr.val)
return result
def inorder_traversal(root):
output=[]
if not root:
return output
stack =[(root,1)]
while stack:
node, count = stack.pop()
if count == 2:
output.append(node.val)
if node.right:
stack.append((node.right, 1))
if count ==1:
stack.append((node, count+1))
if node.left:
stack.append((node.left,1))
return output
class Solution(object):
def inOrder(self, root):
"""
input: TreeNode root
return: Integer[]
"""
# write your solution here
result = []
line = []
curr = root
while curr or line:
if curr:
line.append(curr)
curr = curr.left
else:
curr = line.pop()
result.append(curr.val)
curr = curr.right
return result
def postorder_traversal(root):
output=[]
if not root:
return output
stack =[(root,1)]
while stack:
node, count = stack.pop()
if count == 3:
output.append(node.val)
if count ==1:
stack.append((node, count+1))
if node.left:
stack.append((node.left, 1))
if count ==2:
stack.append((node, count+1))
if node.right:
stack.append((node.right, 1))
return output
class Solution(object):
def postOrder(self, root):
"""
input: TreeNode root
return: Integer[]
"""
# write your solution here
result = []
if not root:
return result
line = [root]
prev = None
while line:
curr = line[-1]
if not prev or curr==prev.left or curr==prev.right:
if curr.left:
line.append(curr.left)
elif curr.right:
line.append(curr.right)
else:
line.pop()
result.append(curr.val)
elif prev==curr.right or prev==curr.left and not curr.right:
line.pop()
result.append(curr.val)
else:
line.append(curr.right)
prev = curr
return result
def print_by_level(root):
q = [root]
nextline = []
line = []
while q:
head = q.pop(0)
if head.left:
nextline.append(head.left)
if head.right:
nextline.append(head.right)
line.append(head.val)
if not q:
print(line)
if nextline:
q=nextline
nextline = []
line = []
def minDepth(root):
# Corner Case
if root is None:
return 0
# Create an empty queue for level order traversal
q = []
# Enqueue root and initialize depth as 1
q.append({'node': root , 'depth' : 1})
# Do level order traversal
while(len(q)>0):
# Remove the front queue item
queueItem = q.pop(0)
# Get details of the removed item
node = queueItem['node']
depth = queueItem['depth']
# If this is the first leaf node seen so far
# then return its depth as answer
if node.left is None and node.right is None:
return depth
# If left subtree is not None, add it to queue
if node.left is not None:
q.append({'node' : node.left , 'depth' : depth+1})
# if right subtree is not None, add it to queue
if node.right is not None:
q.append({'node': node.right , 'depth' : depth+1})
def levelOrder(self, root):
if not root:
return []
queue = deque([root]) #queue=deque() deque.append(root) 注意这里需要[] 因为deque需要接收iterable的参数
result = []
while queue:
count = len(queue)
current_level = []
while count > 0:
node = queue.popleft()
current_level.append(node.value)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
count-=1
result.append(current_level)
return result
def zigzag (self, root):
if not root:
return []
reverse = True
res = []
q = [root]
next = []
line = []
while q:
head = q.pop(0)
if head.left:
next.append(head.left)
if head.right:
next.append(head.right)
line.append(head.val)
if not q:
if reverse:
res.extend(line[::-1])
else:
res.extend(line)
if next:
q = next
reverse = not reverse
next = []
line = []
return res
class Solution (object):
def findHeight(self, root):
if root is None:
return 0
self.result=0
self.helper(root, 0) #还没有任何操作,没有任何计算,height=0
return self.result
def helper(self, root, depth):
if root is None:
self.result = max(self.result, depth)
return
self.helper(root.left, depth+1)
self.helper(root.right, depth+1)
return
class Solution:
def maxValue(self, root):
self.max = None
self.helper(root)
return self.max
def helper(self, root):
if root is None:
return
self.max = max(self.max, root.value)
self.helper(root.left)
self.helper(root.right)
class Solution:
def maxValue(self, root):
if root is None
return None
left = self.maxValue(root.left)
right = self.maxValue(root.right)
return max(root.vale, left, right)
class Solution():
def hasPathSum(self, root, sum):
self.sum = sum
self.ret = False #先假定False,只要在Line13找到一条True,之后的ret都是True
self.helper(root, 0)
return self.ret
def helper(self, root, current):
if self.ret == True:
return
if root is None:
return
if root.left is None and root.right is None
self.ret = (self.ret or (current+root.val == self.sum))
return
self.helper(root.left, current+root.val)
self.helper(root.right, current+root.val)
return
class Solution(object):
def hasPathSum(self, root, sum):
self.sum = sum
if root is None:
return False
self.ret = False
self.helper(root,root.val)
return self.ret
def helper(self, root, current):
if root is None:
return
if root.left is None and root.right is None:
self.ret = (self.ret or current== self.sum)
return
if root.left:
self.helper(root.left, current+root.left.val)
if root.right:
self.helper(root.right, current+root.right.val)
class Solution(object):
def hasPathSum(self, root, sum):
return self.sumPath(root, 0, target)
def sumPath(self, curr, partial, target):
if curr is None:
return False
partial += curr.val
if not curr.left and not curr.right:
return partial==target
return self.sumPath(curr.left, partial, target) or self.sumPath(curr.right, partial, target)
class Solution(object):
def hasPathSum(self, root, sum):
if not root:
return False
if not root.left and not root.left and root.val==sum:
return True
sum-=root.val
return self.hasPathSum(root.left, sum) or self.hasPathSum(root.right, sum)