剑指offer-二叉树
1. 平衡二叉树
输入一棵二叉树,判断该二叉树是否是平衡二叉树。
解:
要么是一颗空树,要么左右子树都是平衡二叉树且左右子树深度之差不超过1
1 # class TreeNode: 2 # def __init__(self, x): 3 # self.val = x 4 # self.left = None 5 # self.right = None 6 class Solution: 7 def IsBalanced_Solution(self, pRoot): 8 # write code here 9 if not pRoot: 10 return True 11 res = abs(self.getDepth(pRoot.left) - self.getDepth(pRoot.right)) 12 if res <= 1 and self.IsBalanced_Solution(pRoot.left) and self.IsBalanced_Solution(pRoot.right): 13 return True 14 return False 15 16 def getDepth(self, root): 17 if not root: 18 return 0 19 if not (root.left or root.right): 20 return 1 21 return max(self.getDepth(root.left), self.getDepth(root.right)) + 1
2. 二叉树的深度
输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
解:
层次遍历,bfs 实现
1 # class TreeNode: 2 # def __init__(self, x): 3 # self.val = x 4 # self.left = None 5 # self.right = None 6 class Solution: 7 def TreeDepth(self, pRoot): 8 # write code here 9 if not pRoot: 10 return 0 11 depth = 0 12 queue = [pRoot] 13 while queue: 14 tmp = [] 15 for i in range(len(queue)): 16 node = queue.pop(0) 17 tmp.append(node.val) 18 if node.left: 19 queue.append(node.left) 20 if node.right: 21 queue.append(node.right) 22 if tmp: 23 depth += 1 24 return depth
dfs 实现,只需要记录深度即可,不用记录节点
1 # class TreeNode: 2 # def __init__(self, x): 3 # self.val = x 4 # self.left = None 5 # self.right = None 6 class Solution: 7 def TreeDepth(self, pRoot): 8 # write code here 9 if not pRoot: 10 return 0 11 self.depth = 0 12 def helper(node, level): 13 if not(node.left or node.right): 14 self.depth = max(self.depth, level) 15 return 16 if node.left: 17 helper(node.left, level+1) 18 if node.right: 19 helper(node.right, level+1) 20 21 helper(pRoot, 1) 22 return self.depth
3. 二叉树的下一个节点
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
解:
几种可能的情况考虑一下即可
1 # class TreeLinkNode: 2 # def __init__(self, x): 3 # self.val = x 4 # self.left = None 5 # self.right = None 6 # self.next = None 7 class Solution: 8 def GetNext(self, pNode): 9 # write code here 10 if not pNode: 11 return 12 13 # 如果当前节点有右子树,中序遍历的下一个节点是其右子树的最左节点 14 if pNode.right: 15 pRight = pNode.right 16 while pRight.left: 17 pRight = pRight.left 18 return pRight 19 20 # 如果当前节点没有右子树,但是当前节点是其父节点的左子节点,下一个节点是其父节点 21 if pNode.next and pNode.next.left == pNode: 22 return pNode.next 23 24 # 如果当前节点没有右子树,但是是其父节点的右子节点,则一直向上遍历,找到是其父节点的左子结点的pNode 25 # 当前节点的下一个节点就是pNode的父节点 26 if pNode.next and pNode.next.right == pNode: 27 while pNode.next and pNode != pNode.next.left: 28 pNode = pNode.next 29 return pNode.next 30 return
4. 对称的二叉树
请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
解:
递归实现,判断给定两个节点为根的子树是否镜像,首先根节点的值要相等,其次A的左子树和B的右子树、A的右子树和B的左子树要递归的进行判断
1 # class TreeNode: 2 # def __init__(self, x): 3 # self.val = x 4 # self.left = None 5 # self.right = None 6 class Solution: 7 def isSymmetrical(self, pRoot): 8 # write code here 9 if not pRoot: 10 return True 11 return self.compare(pRoot.left, pRoot.right) 12 13 def compare(self, p1, p2): 14 if p1 == None : 15 return p2 == None 16 if p2 == None: 17 return False 18 if p1.val != p2.val: 19 return False 20 return self.compare(p1.left, p2.right) and self.compare(p1.right, p2.left)
dfs,用栈实现,成对取出成对插入,镜像:左左配右右,左右配右左
1 # class TreeNode: 2 # def __init__(self, x): 3 # self.val = x 4 # self.left = None 5 # self.right = None 6 class Solution: 7 def isSymmetrical(self, pRoot): 8 # write code here 9 if not pRoot: 10 return True 11 stack = [pRoot.left, pRoot.right] 12 13 while stack: 14 right = stack.pop() # 成对取出 15 left = stack.pop() 16 if left == None and right == None: 17 continue 18 if left == None or right == None: 19 return False 20 if left.val != right.val: 21 return False 22 23 # 成对插入 24 stack.append(left.left) 25 stack.append(right.right) 26 stack.append(left.right) 27 stack.append(right.left) 28 29 return True
bfs,队列实现
1 # class TreeNode: 2 # def __init__(self, x): 3 # self.val = x 4 # self.left = None 5 # self.right = None 6 class Solution: 7 def isSymmetrical(self, pRoot): 8 # write code here 9 if not pRoot: 10 return True 11 queue = [pRoot.left, pRoot.right] 12 13 while queue: 14 left = queue.pop(0) # 成对取出 15 right = queue.pop(0) 16 if left == None and right == None: 17 continue 18 if left == None or right == None: 19 return False 20 if left.val != right.val: 21 return False 22 23 # 成对插入 24 queue.append(left.left) 25 queue.append(right.right) 26 queue.append(left.right) 27 queue.append(right.left) 28 29 return True
5. 把二叉树打印成多行
从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。
解:
层次遍历,bfs
1 # class TreeNode: 2 # def __init__(self, x): 3 # self.val = x 4 # self.left = None 5 # self.right = None 6 class Solution: 7 # 返回二维列表[[1,2],[4,5]] 8 def Print(self, pRoot): 9 # write code here 10 if not pRoot: 11 return [] 12 res = [] 13 queue = [pRoot] 14 while queue: 15 tmp = [] 16 for i in range(len(queue)): 17 node = queue.pop(0) 18 tmp.append(node.val) 19 if node.left: 20 queue.append(node.left) 21 if node.right: 22 queue.append(node.right) 23 if tmp: 24 res.append(tmp) 25 return res
dfs
1 # class TreeNode: 2 # def __init__(self, x): 3 # self.val = x 4 # self.left = None 5 # self.right = None 6 class Solution: 7 # 返回二维列表[[1,2],[4,5]] 8 def Print(self, pRoot): 9 # write code here 10 if not pRoot: 11 return [] 12 self.res = [] 13 14 def helper(node, level): 15 if not node: 16 return 17 if level == len(self.res): 18 self.res.append([]) 19 self.res[level].append(node.val) 20 if node.left: 21 helper(node.left, level + 1) 22 if node.right: 23 helper(node.right, level + 1) 24 25 helper(pRoot, 0) 26 return self.res
6. 按之字形顺序打印二叉树
请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。
解:
还是层次遍历,用一个 flag 控制每一层是正序还是逆序
1 # class TreeNode: 2 # def __init__(self, x): 3 # self.val = x 4 # self.left = None 5 # self.right = None 6 class Solution: 7 def Print(self, pRoot): 8 # write code here 9 if not pRoot: 10 return [] 11 leftToRight = True 12 queue = [pRoot] 13 res = [] 14 while queue: 15 tmp = [] 16 for i in range(len(queue)): 17 node = queue.pop(0) 18 tmp.append(node.val) 19 if node.left: 20 queue.append(node.left) 21 if node.right: 22 queue.append(node.right) 23 if tmp: 24 if leftToRight: 25 res.append(tmp) 26 else: 27 res.append(tmp[::-1]) 28 leftToRight = not leftToRight 29 return res
7. 序列化二叉树
二叉树的反序列化是指:根据某种遍历顺序得到的序列化字符串结果str,重构二叉树。
1 # class TreeNode: 2 # def __init__(self, x): 3 # self.val = x 4 # self.left = None 5 # self.right = None 6 class Solution: 7 def __init__(self): 8 self.flag = -1 9 def Serialize(self, root): 10 # write code here 11 if not root: 12 return '#!' 13 return str(root.val)+'!'+self.Serialize(root.left)+self.Serialize(root.right) 14 15 def Deserialize(self, s): 16 # write code here 17 self.flag += 1 18 vals = s.split('!') 19 if self.flag >= len(vals): 20 return None 21 root = None 22 if vals[self.flag] != '#': 23 root = TreeNode(int(vals[self.flag])) 24 root.left = self.Deserialize(s) 25 root.right = self.Deserialize(s) 26 return root
8. 二叉搜索树的第k个节点
给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4。
解:
中序遍历即有序
1 # class TreeNode: 2 # def __init__(self, x): 3 # self.val = x 4 # self.left = None 5 # self.right = None 6 class Solution: 7 # 返回对应节点TreeNode 8 def KthNode(self, pRoot, k): 9 # write code here 10 if not pRoot: 11 return None 12 self.res = [] 13 self.midOrdTrav(pRoot) 14 return self.res[k-1] if 0<k<=len(self.res) else None 15 16 def midOrdTrav(self, root): 17 if not root: 18 return 19 self.midOrdTrav(root.left) 20 self.res.append(root) 21 self.midOrdTrav(root.right)
中序遍历的时候维护一个计数器,到 k 个数了就返回
1 # class TreeNode: 2 # def __init__(self, x): 3 # self.val = x 4 # self.left = None 5 # self.right = None 6 class Solution: 7 # 返回对应节点TreeNode 8 def KthNode(self, pRoot, k): 9 # write code here 10 if not pRoot: 11 return None 12 13 count = 0 14 stack = [] 15 p = pRoot 16 while p or stack: 17 while p: 18 stack.append(p) 19 p = p.left 20 if stack: 21 p = stack.pop() 22 count += 1 23 if count == k: 24 return p 25 p = p.right 26 return None
1 import heapq 2 class Solution: 3 def __init__(self): 4 self.small = [] # 小的数,大顶堆 5 self.large = [] # 大的数,小顶堆 6 7 def Insert(self, num): 8 # write code here 9 heapq.heappush(self.small, -heapq.heappushpop(self.large, num)) 10 if len(self.large) < len(self.small): 11 heapq.heappush(self.large, -heapq.heappop(self.small)) 12 13 def GetMedian(self, default=None): 14 # write code here 15 if len(self.large) > len(self.small): 16 return float(self.large[0]) 17 return (self.large[0] - self.small[0])/2.
1 # class TreeNode: 2 # def __init__(self, x): 3 # self.val = x 4 # self.left = None 5 # self.right = None 6 class Solution: 7 # 返回构造的TreeNode根节点 8 def reConstructBinaryTree(self, pre, tin): 9 # write code here 10 if not pre or not tin: 11 return None 12 root = TreeNode(pre[0]) 13 index = self.Search(tin, root.val) # tin.index(root.val) 14 root.left = self.reConstructBinaryTree(pre[1:index+1], tin[:index]) 15 root.right = self.reConstructBinaryTree(pre[index+1:], tin[index+1:]) 16 return root 17 18 def Search(self, nums, target): 19 if not nums: 20 return -1 21 n = len(nums) 22 for i in range(n): 23 if nums[i] == target: 24 return i 25 return -1