二叉树篇
111. 二叉树的最小深度
- 思路1:二叉树的最小深度需分情况讨论:节点无左孩子,则为右子树深度加1;无右孩子,则为左子树深度加1;左右孩子都有,为左子树和右子树深度较小值加1
class Solution(object):
def minDepth(self, root):
if not root: return 0
if not root.left: return self.minDepth(root.right) + 1
if not root.right: return self.minDepth(root.left) + 1
return min(self.minDepth(root.left),self.minDepth(root.right)) + 1
55-I. 二叉树的深度
- 思路1:二叉树的深度为 左右子树深度的最大值+1
class Solution(object):
def maxDepth(self, root):
if not root: return 0
return max(self.maxDepth(root.left),self.maxDepth(root.right)) + 1
55-II. 平衡二叉树
- 思路1:从上到下 以先序遍历的方式 遍历每个节点,并计算 每个节点的左右子树深度,如果深度差超过1,则不为平衡二叉树
class Solution(object):
def isBalanced(self, root):
if not root: return True;
d_left = self.dfs(root.left)
d_right = self.dfs(root.right)
if abs(d_left-d_right) > 1: return False
a = self.isBalanced(root.left)
b = self.isBalanced(root.right)
return a and b
def dfs(self,root):
if not root: return 0
return max(self.dfs(root.left),self.dfs(root.right))+1
总结:求平衡二叉树,关键在于去求 子树的深度
543. 二叉树的直径
- 思路1:直径实际上是左右子树的深度和的最大值,写dfs去求子树深度,用成员变量self.ret去获取整个求子树深度过程中,所有子树直径的最大值
class Solution(object):
def __init__(self):
self.ret = 0
def diameterOfBinaryTree(self, root):
if not root: return 0
self.dfs(root)
return self.ret
def dfs(self,root):
if not root: return 0
a = self.dfs(root.left)
b = self.dfs(root.right)
self.ret = max(self.ret,a+b)
return max(a,b) + 1
总结:求二叉树的直径,关键在于求二叉树的深度
100. 相同的树
- 思路1:先判断两棵树对应节点是否同时为None,在都不为None情况下再去判断对应节点的val是否一样
class Solution(object):
def isSameTree(self, p, q):
if not p and not q: return True
if (not p)^(not q): return False
if p.val != q.val: return False
a = self.isSameTree(p.left,q.left)
b = self.isSameTree(p.right,q.right)
return a and b
28. 对称的二叉树
- 思路1: 先判断左右子树对称节点是否同时为None,在都不为None情况下再去判断对称节点的val是否一样 **
class Solution(object):
def isSymmetric(self, root):
if not root: return True
return self.dfs(root.left,root.right)
def dfs(self,p,q):
if not p and not q: return True
if (not p)^(not q): return False
if p.val!=q.val: return False
a = self.dfs(p.left,q.right)
b = self.dfs(p.right,q.left)
return a and b
26. 树的子结构
- 思路1:判断B是A 或 是A左孩子 或是A右孩子的子结构?满足一个即可。判断子结构 先判断两棵树对应节点是否同时为None,在都不为None情况下再去判断对应节点的val是否一样
class Solution(object):
def isSubStructure(self, A, B):
if not A or not B: return False
c = self.dfs(A,B)
a = self.isSubStructure(A.left,B)
b = self.isSubStructure(A.right,B)
return a or b or c
def dfs(self,A,B):
if not B: return True
if (not A)^(not B): return False
if A.val!=B.val: return False
a = self.dfs(A.left,B.left)
b = self.dfs(A.right,B.right)
return a and b
27. 二叉树的镜像
- 思路1:只需递归将 root节点的左右孩子指向交换即可
class Solution(object):
def mirrorTree(self, root):
if not root: return
root.left,root.right = root.right,root.left
self.mirrorTree(root.left)
self.mirrorTree(root.right)
return root
617. 合并二叉树
- 思路1:判断两颗二叉树是否都为None,在都不为None情况下,新建root节点,其值为两颗树对应节点val的和
class Solution(object):
def mergeTrees(self, root1, root2):
if not root1 and not root2: return None
if root1 and not root2: return root1
if not root1 and root2: return root2
if root1 and root2:
root = TreeNode(0)
root.val = root1.val + root2.val
root.left = self.mergeTrees(root1.left,root2.left)
root.right = self.mergeTrees(root1.right,root2.right)
return root
222. 完全二叉树的节点个数
思路1:直接求二叉树节点个数 为左子树个数+右子树个数+根节点(为1)
思路2:计算完全二叉树的深度L,根据深度算出前L-1层的节点个数,然后采取后序遍历统计最后一层节点个数(后序遍历也要遍历所有元素,时间复杂度并没有降低)
思路3:先求树深度,对树进行计数下标标记,根节点从1开始,后续节点依次加1。然后对最后一层计数下标进行二分查找(判断该mid节点是否在二叉树中,根据位运算找到mid节点位置,判断mid节点是否位None来进行二分),查找到最后一个节点的 计数下标时,即为完全二叉树节点个数
# 思路1
class Solution(object):
def countNodes(self, root):
if not root: return 0
return self.countNodes(root.left) + self.countNodes(root.right) + 1
# 思路2
class Solution(object):
def __init__(self):
self.cnt = 0
def countNodes(self, root):
if not root: return 0
depth = self.depth(root)
self.dfs(root,depth,1)
return pow(2,depth-1)-1 + self.cnt
def depth(self,root):
if not root: return 0
return self.depth(root.left) + 1
def dfs(self,root,depth,k):
if not root: return
self.dfs(root.left,depth,k+1)
self.dfs(root.right,depth,k+1)
# 后序遍历
if k==depth:
self.cnt += 1
else:
return
# 思路3
class Solution(object):
def countNodes(self, root):
if not root: return 0
level,node = 0,root
while node.left: # 求深度
level += 1
node = node.left
low = 1 << level
high = (1 << (level + 1)) - 1;
while low < high: # 二分法
mid = (high - low + 1) // 2 + low # 根节点计数下标1,然后依次加1,mid代表最后一层 中间节点计数下标
if self.exists(root, level, mid): # 判断中间下标节点 是否在树中(不在则为None,在则不为None)
low = mid # 不为None,说明最终节点在mid右侧
else:
high = mid - 1
return low # low为最后一个节点计数下标
def exists(self,root,level,k):
bits = 1 << (level - 1) # 最多循环level次,从root节点去 寻找与mid计数下标对应的节点
node = root
while bits > 0: # 这个很巧妙
if not (bits & k): # 根据mid节点的 每一位来判断 在树的哪个子树
node = node.left
else:
node = node.right
bits >>= 1
return node != None
版权声明:本文为qq_38861679原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。