1. 平衡二叉树

输入一棵二叉树,判断该二叉树是否是平衡二叉树。

解:

要么是一颗空树,要么左右子树都是平衡二叉树且左右子树深度之差不超过1

  1. 1 # class TreeNode:
  2. 2 # def __init__(self, x):
  3. 3 # self.val = x
  4. 4 # self.left = None
  5. 5 # self.right = None
  6. 6 class Solution:
  7. 7 def IsBalanced_Solution(self, pRoot):
  8. 8 # write code here
  9. 9 if not pRoot:
  10. 10 return True
  11. 11 res = abs(self.getDepth(pRoot.left) - self.getDepth(pRoot.right))
  12. 12 if res <= 1 and self.IsBalanced_Solution(pRoot.left) and self.IsBalanced_Solution(pRoot.right):
  13. 13 return True
  14. 14 return False
  15. 15
  16. 16 def getDepth(self, root):
  17. 17 if not root:
  18. 18 return 0
  19. 19 if not (root.left or root.right):
  20. 20 return 1
  21. 21 return max(self.getDepth(root.left), self.getDepth(root.right)) + 1

  

2. 二叉树的深度

输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。

解:

层次遍历,bfs 实现

  1. 1 # class TreeNode:
  2. 2 # def __init__(self, x):
  3. 3 # self.val = x
  4. 4 # self.left = None
  5. 5 # self.right = None
  6. 6 class Solution:
  7. 7 def TreeDepth(self, pRoot):
  8. 8 # write code here
  9. 9 if not pRoot:
  10. 10 return 0
  11. 11 depth = 0
  12. 12 queue = [pRoot]
  13. 13 while queue:
  14. 14 tmp = []
  15. 15 for i in range(len(queue)):
  16. 16 node = queue.pop(0)
  17. 17 tmp.append(node.val)
  18. 18 if node.left:
  19. 19 queue.append(node.left)
  20. 20 if node.right:
  21. 21 queue.append(node.right)
  22. 22 if tmp:
  23. 23 depth += 1
  24. 24 return depth

  

dfs 实现,只需要记录深度即可,不用记录节点

  1. 1 # class TreeNode:
  2. 2 # def __init__(self, x):
  3. 3 # self.val = x
  4. 4 # self.left = None
  5. 5 # self.right = None
  6. 6 class Solution:
  7. 7 def TreeDepth(self, pRoot):
  8. 8 # write code here
  9. 9 if not pRoot:
  10. 10 return 0
  11. 11 self.depth = 0
  12. 12 def helper(node, level):
  13. 13 if not(node.left or node.right):
  14. 14 self.depth = max(self.depth, level)
  15. 15 return
  16. 16 if node.left:
  17. 17 helper(node.left, level+1)
  18. 18 if node.right:
  19. 19 helper(node.right, level+1)
  20. 20
  21. 21 helper(pRoot, 1)
  22. 22 return self.depth

  

3. 二叉树的下一个节点

给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。

解:

几种可能的情况考虑一下即可

  1. 1 # class TreeLinkNode:
  2. 2 # def __init__(self, x):
  3. 3 # self.val = x
  4. 4 # self.left = None
  5. 5 # self.right = None
  6. 6 # self.next = None
  7. 7 class Solution:
  8. 8 def GetNext(self, pNode):
  9. 9 # write code here
  10. 10 if not pNode:
  11. 11 return
  12. 12
  13. 13 # 如果当前节点有右子树,中序遍历的下一个节点是其右子树的最左节点
  14. 14 if pNode.right:
  15. 15 pRight = pNode.right
  16. 16 while pRight.left:
  17. 17 pRight = pRight.left
  18. 18 return pRight
  19. 19
  20. 20 # 如果当前节点没有右子树,但是当前节点是其父节点的左子节点,下一个节点是其父节点
  21. 21 if pNode.next and pNode.next.left == pNode:
  22. 22 return pNode.next
  23. 23
  24. 24 # 如果当前节点没有右子树,但是是其父节点的右子节点,则一直向上遍历,找到是其父节点的左子结点的pNode
  25. 25 # 当前节点的下一个节点就是pNode的父节点
  26. 26 if pNode.next and pNode.next.right == pNode:
  27. 27 while pNode.next and pNode != pNode.next.left:
  28. 28 pNode = pNode.next
  29. 29 return pNode.next
  30. 30 return

  

4. 对称的二叉树

请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。

解:

递归实现,判断给定两个节点为根的子树是否镜像,首先根节点的值要相等,其次A的左子树和B的右子树、A的右子树和B的左子树要递归的进行判断

  1. 1 # class TreeNode:
  2. 2 # def __init__(self, x):
  3. 3 # self.val = x
  4. 4 # self.left = None
  5. 5 # self.right = None
  6. 6 class Solution:
  7. 7 def isSymmetrical(self, pRoot):
  8. 8 # write code here
  9. 9 if not pRoot:
  10. 10 return True
  11. 11 return self.compare(pRoot.left, pRoot.right)
  12. 12
  13. 13 def compare(self, p1, p2):
  14. 14 if p1 == None :
  15. 15 return p2 == None
  16. 16 if p2 == None:
  17. 17 return False
  18. 18 if p1.val != p2.val:
  19. 19 return False
  20. 20 return self.compare(p1.left, p2.right) and self.compare(p1.right, p2.left)

  

dfs,用栈实现,成对取出成对插入,镜像:左左配右右,左右配右左

  1. 1 # class TreeNode:
  2. 2 # def __init__(self, x):
  3. 3 # self.val = x
  4. 4 # self.left = None
  5. 5 # self.right = None
  6. 6 class Solution:
  7. 7 def isSymmetrical(self, pRoot):
  8. 8 # write code here
  9. 9 if not pRoot:
  10. 10 return True
  11. 11 stack = [pRoot.left, pRoot.right]
  12. 12
  13. 13 while stack:
  14. 14 right = stack.pop() # 成对取出
  15. 15 left = stack.pop()
  16. 16 if left == None and right == None:
  17. 17 continue
  18. 18 if left == None or right == None:
  19. 19 return False
  20. 20 if left.val != right.val:
  21. 21 return False
  22. 22
  23. 23 # 成对插入
  24. 24 stack.append(left.left)
  25. 25 stack.append(right.right)
  26. 26 stack.append(left.right)
  27. 27 stack.append(right.left)
  28. 28
  29. 29 return True

bfs,队列实现

  1. 1 # class TreeNode:
  2. 2 # def __init__(self, x):
  3. 3 # self.val = x
  4. 4 # self.left = None
  5. 5 # self.right = None
  6. 6 class Solution:
  7. 7 def isSymmetrical(self, pRoot):
  8. 8 # write code here
  9. 9 if not pRoot:
  10. 10 return True
  11. 11 queue = [pRoot.left, pRoot.right]
  12. 12
  13. 13 while queue:
  14. 14 left = queue.pop(0) # 成对取出
  15. 15 right = queue.pop(0)
  16. 16 if left == None and right == None:
  17. 17 continue
  18. 18 if left == None or right == None:
  19. 19 return False
  20. 20 if left.val != right.val:
  21. 21 return False
  22. 22
  23. 23 # 成对插入
  24. 24 queue.append(left.left)
  25. 25 queue.append(right.right)
  26. 26 queue.append(left.right)
  27. 27 queue.append(right.left)
  28. 28
  29. 29 return True

  

5. 把二叉树打印成多行

从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。

解:

层次遍历,bfs

  1. 1 # class TreeNode:
  2. 2 # def __init__(self, x):
  3. 3 # self.val = x
  4. 4 # self.left = None
  5. 5 # self.right = None
  6. 6 class Solution:
  7. 7 # 返回二维列表[[1,2],[4,5]]
  8. 8 def Print(self, pRoot):
  9. 9 # write code here
  10. 10 if not pRoot:
  11. 11 return []
  12. 12 res = []
  13. 13 queue = [pRoot]
  14. 14 while queue:
  15. 15 tmp = []
  16. 16 for i in range(len(queue)):
  17. 17 node = queue.pop(0)
  18. 18 tmp.append(node.val)
  19. 19 if node.left:
  20. 20 queue.append(node.left)
  21. 21 if node.right:
  22. 22 queue.append(node.right)
  23. 23 if tmp:
  24. 24 res.append(tmp)
  25. 25 return res

  

dfs

  1. 1 # class TreeNode:
  2. 2 # def __init__(self, x):
  3. 3 # self.val = x
  4. 4 # self.left = None
  5. 5 # self.right = None
  6. 6 class Solution:
  7. 7 # 返回二维列表[[1,2],[4,5]]
  8. 8 def Print(self, pRoot):
  9. 9 # write code here
  10. 10 if not pRoot:
  11. 11 return []
  12. 12 self.res = []
  13. 13
  14. 14 def helper(node, level):
  15. 15 if not node:
  16. 16 return
  17. 17 if level == len(self.res):
  18. 18 self.res.append([])
  19. 19 self.res[level].append(node.val)
  20. 20 if node.left:
  21. 21 helper(node.left, level + 1)
  22. 22 if node.right:
  23. 23 helper(node.right, level + 1)
  24. 24
  25. 25 helper(pRoot, 0)
  26. 26 return self.res

  

6. 按之字形顺序打印二叉树

请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。

解:

还是层次遍历,用一个 flag 控制每一层是正序还是逆序

  1. 1 # class TreeNode:
  2. 2 # def __init__(self, x):
  3. 3 # self.val = x
  4. 4 # self.left = None
  5. 5 # self.right = None
  6. 6 class Solution:
  7. 7 def Print(self, pRoot):
  8. 8 # write code here
  9. 9 if not pRoot:
  10. 10 return []
  11. 11 leftToRight = True
  12. 12 queue = [pRoot]
  13. 13 res = []
  14. 14 while queue:
  15. 15 tmp = []
  16. 16 for i in range(len(queue)):
  17. 17 node = queue.pop(0)
  18. 18 tmp.append(node.val)
  19. 19 if node.left:
  20. 20 queue.append(node.left)
  21. 21 if node.right:
  22. 22 queue.append(node.right)
  23. 23 if tmp:
  24. 24 if leftToRight:
  25. 25 res.append(tmp)
  26. 26 else:
  27. 27 res.append(tmp[::-1])
  28. 28 leftToRight = not leftToRight
  29. 29 return res

7. 序列化二叉树

请实现两个函数,分别用来序列化和反序列化二叉树
二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保存。序列化可以基于先序、中序、后序、层序的二叉树遍历方式来进行修改,序列化的结果是一个字符串,序列化时通过 某种符号表示空节点(#),以 ! 表示一个结点值的结束(value!)。
二叉树的反序列化是指:根据某种遍历顺序得到的序列化字符串结果str,重构二叉树。
解:
这题的序列化就直接前序遍历实现即可,注意按要求用字符 # 和 !表示空节点和结束符。
主要问题在反序列化上,还是按照根左右的顺序递归,用 flag 来控制递归过程中,反序列化的节点值在数组中的索引,flag从0开始,每次都+1,遇到‘#’说明是空节点,不需要构造node
  1. 1 # class TreeNode:
  2. 2 # def __init__(self, x):
  3. 3 # self.val = x
  4. 4 # self.left = None
  5. 5 # self.right = None
  6. 6 class Solution:
  7. 7 def __init__(self):
  8. 8 self.flag = -1
  9. 9 def Serialize(self, root):
  10. 10 # write code here
  11. 11 if not root:
  12. 12 return '#!'
  13. 13 return str(root.val)+'!'+self.Serialize(root.left)+self.Serialize(root.right)
  14. 14
  15. 15 def Deserialize(self, s):
  16. 16 # write code here
  17. 17 self.flag += 1
  18. 18 vals = s.split('!')
  19. 19 if self.flag >= len(vals):
  20. 20 return None
  21. 21 root = None
  22. 22 if vals[self.flag] != '#':
  23. 23 root = TreeNode(int(vals[self.flag]))
  24. 24 root.left = self.Deserialize(s)
  25. 25 root.right = self.Deserialize(s)
  26. 26 return root

8. 二叉搜索树的第k个节点

给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8)    中,按结点数值大小顺序第三小结点的值为4。

解:

中序遍历即有序

  1. 1 # class TreeNode:
  2. 2 # def __init__(self, x):
  3. 3 # self.val = x
  4. 4 # self.left = None
  5. 5 # self.right = None
  6. 6 class Solution:
  7. 7 # 返回对应节点TreeNode
  8. 8 def KthNode(self, pRoot, k):
  9. 9 # write code here
  10. 10 if not pRoot:
  11. 11 return None
  12. 12 self.res = []
  13. 13 self.midOrdTrav(pRoot)
  14. 14 return self.res[k-1] if 0<k<=len(self.res) else None
  15. 15
  16. 16 def midOrdTrav(self, root):
  17. 17 if not root:
  18. 18 return
  19. 19 self.midOrdTrav(root.left)
  20. 20 self.res.append(root)
  21. 21 self.midOrdTrav(root.right)

  

中序遍历的时候维护一个计数器,到 k 个数了就返回

  1. 1 # class TreeNode:
  2. 2 # def __init__(self, x):
  3. 3 # self.val = x
  4. 4 # self.left = None
  5. 5 # self.right = None
  6. 6 class Solution:
  7. 7 # 返回对应节点TreeNode
  8. 8 def KthNode(self, pRoot, k):
  9. 9 # write code here
  10. 10 if not pRoot:
  11. 11 return None
  12. 12
  13. 13 count = 0
  14. 14 stack = []
  15. 15 p = pRoot
  16. 16 while p or stack:
  17. 17 while p:
  18. 18 stack.append(p)
  19. 19 p = p.left
  20. 20 if stack:
  21. 21 p = stack.pop()
  22. 22 count += 1
  23. 23 if count == k:
  24. 24 return p
  25. 25 p = p.right
  26. 26 return None

 

 
9.数据流中的中位数
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
解:
维护两个堆,大顶堆用来存较小的数,从大到小排列;小顶堆用来存较大的数,从小到大排列。
保证小顶堆中的元素都大于等于大顶堆中的元素(始终保证较大数的那一半多一个或者一样多,中位数始终在这一边),所以 insert 的时候先 push 进小顶堆(存较大的数),再把小顶堆中的最小值 pop 出来 push 到大顶堆(存较小的数)中。
每次都检查,如果小顶堆的元素个数小于大顶堆的元素个数(较大的数比较小的数少了),就把大顶堆中的最大值 pop 出来 push 小顶堆。
取中位数的时候,如果当前两个堆一样多,显然是取小顶堆和大顶堆根结点的平均值;如果当前小顶堆元素个数多一个,显然是取小顶堆的根节点
  1. 1 import heapq
  2. 2 class Solution:
  3. 3 def __init__(self):
  4. 4 self.small = [] # 小的数,大顶堆
  5. 5 self.large = [] # 大的数,小顶堆
  6. 6
  7. 7 def Insert(self, num):
  8. 8 # write code here
  9. 9 heapq.heappush(self.small, -heapq.heappushpop(self.large, num))
  10. 10 if len(self.large) < len(self.small):
  11. 11 heapq.heappush(self.large, -heapq.heappop(self.small))
  12. 12
  13. 13 def GetMedian(self, default=None):
  14. 14 # write code here
  15. 15 if len(self.large) > len(self.small):
  16. 16 return float(self.large[0])
  17. 17 return (self.large[0] - self.small[0])/2.

  

 
10. 重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
解:
其实就是一个递归的过程,每次找一下根节点在哪,进而定位好左右子树的切片,构建好了根节点之后再分别去构建左右子树
  1. 1 # class TreeNode:
  2. 2 # def __init__(self, x):
  3. 3 # self.val = x
  4. 4 # self.left = None
  5. 5 # self.right = None
  6. 6 class Solution:
  7. 7 # 返回构造的TreeNode根节点
  8. 8 def reConstructBinaryTree(self, pre, tin):
  9. 9 # write code here
  10. 10 if not pre or not tin:
  11. 11 return None
  12. 12 root = TreeNode(pre[0])
  13. 13 index = self.Search(tin, root.val) # tin.index(root.val)
  14. 14 root.left = self.reConstructBinaryTree(pre[1:index+1], tin[:index])
  15. 15 root.right = self.reConstructBinaryTree(pre[index+1:], tin[index+1:])
  16. 16 return root
  17. 17
  18. 18 def Search(self, nums, target):
  19. 19 if not nums:
  20. 20 return -1
  21. 21 n = len(nums)
  22. 22 for i in range(n):
  23. 23 if nums[i] == target:
  24. 24 return i
  25. 25 return -1

剑指offer-二叉树的更多相关文章

  1. 剑指Offer——二叉树

    剑指Offer--二叉树 前言 数据结构通常是编程面试中考察的重点.在参加面试之前,应聘者需要熟练掌握链表.树.栈.队列和哈希表等数据结构,以及它们的操作.本片博文主要讲解二叉树操作的相关知识,主要包 ...

  2. 剑指offer 二叉树中和为某一个值的路径

    剑指offer 牛客网 二叉树中和为某一个值的路径 # -*- coding: utf-8 -*- """ Created on Tue Apr 9 15:53:58 2 ...

  3. 剑指offer 二叉树的层序遍历

    剑指offer 牛客网 二叉树的层序遍历 # -*- coding: utf-8 -*- """ Created on Tue Apr 9 09:33:16 2019 @ ...

  4. JS数据结构与算法 - 剑指offer二叉树算法题汇总

    ❗❗ 必看经验 在博主刷题期间,基本上是碰到一道二叉树就不会碰到一道就不会,有时候一个下午都在搞一道题,看别人解题思路就算能看懂,自己写就呵呵了.一气之下不刷了,改而先去把二叉树的基础算法给搞搞懂,然 ...

  5. 剑指offer——二叉树的镜像

    题目:操作给定的二叉树,将其变换为源二叉树的镜像. 思路:前序(根左右的顺序)遍历一棵树,在存储的时候将其左右树进行交换,最后按照处理后的树还原,即得到其镜像. /** public class Tr ...

  6. 剑指Offer 二叉树中和为某一值的路径(dfs)

    题目描述 输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径.     思路: 递归,然后深搜,因为题目定义的, ...

  7. 剑指Offer 二叉树的镜像

    题目描述 操作给定的二叉树,将其变换为源二叉树的镜像. 输入描述: 二叉树的镜像定义:源二叉树 8 / \ 6 10 / \ / \ 5 7 9 11 镜像二叉树 8 / \ 10 6 / \ / \ ...

  8. 剑指Offer——二叉树的下一个结点

    题目描述: 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回.注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针. 分析: 如果该结点存在右子树,那么返回右子树的最左结 ...

  9. 剑指Offer——二叉树的深度

    题目描述: 输入一棵二叉树,求该树的深度.从根结点到叶结点依次经过的结点(含根.叶结点)形成树的一条路径,最长路径的长度为树的深度. 分析: 二叉树的深度等于其左子树的深度和右子树的深度两个中最大的深 ...

  10. 剑指Offer——二叉树中和为某一值的路径

    题目描述: 输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径. 分析: 先序遍历二叉树,找到二叉树中结点值的和 ...

随机推荐

  1. Unity游戏资源反解工具

    https://github.com/ata4/disunity http://devxdevelopment.com/UnityUnpacker 链接:https://pan.baidu.com/s ...

  2. springboot @valid与@validated的参数校验使用总结

    好久没在这平台写博客了,最近整理了这东西,先给出总结 // @Valid只能用在controller,@Validated可以用在其他被spring管理的类上 // @Valid可以加在成员变量上(本 ...

  3. 基于canal的client-adapter数据同步必读指南

    本文将介绍canal项目中client-adapter的使用,以及落地生产中需要考虑的可靠性.高可用与监控报警.(基于canal 1.1.4版本) canal作为mysql的实时数据订阅组件,实现了对 ...

  4. CodeForces - 1114D-Flood Fill (区间dp)

    You are given a line of nn colored squares in a row, numbered from 11 to nn from left to right. The  ...

  5. 深入了解Redis【一】源码下载与参考资料准备

    引言 一直在使用redis,但是却没有系统的了解过它的底层实现,准备边学习边记录,深入了解redis. 打算分析以下几个方面: redis的基本类型及底层原理与java对比,每种数据类型的使用场景 r ...

  6. Kubernetes 服务部署最佳实践(一) ——如何更好地设置 Request 与 Limit

    如何为容器配置 Request 与 Limit? 这是一个即常见又棘手的问题,这个根据服务类型,需求与场景的不同而不同,没有固定的答案,这里结合生产经验总结了一些最佳实践,可以作为参考. 所有容器都应 ...

  7. 项目实战:Qt+Ffmpeg+OpenCV相机程序(打开摄像头、支持多种摄像头、分辨率调整、翻转、旋转、亮度调整、拍照、录像、回放图片、回放录像)

    若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...

  8. Java清空一个指定文件

    清空test.log文件所有内容 File log = new File("c:\\test\\test.log"); FileWriter fileWriter =new Fil ...

  9. Repeater每行绑定事件代码

    if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) { Repea ...

  10. Educational Codeforces Round 95(A-C题解)

    A. Buying Torches 题目:http://codeforces.com/contest/1418/problem/A 题解:计算一个公式:1+n*(x-1)=(y+1)*k,求满足该条件 ...