本篇文章根据labuladong的算法小抄汇总二叉树与二叉搜索树的常见算法,采用python3实现
二叉树 翻转二叉树class TreeNode: def __init__(self,val=0,left=None,right=None): self.val = val self.left = left self.right = right class Solution: def invertTree(self,root): if root is None: return None tmp = root.left root.left = root.right root.right = tmp self.invertTree(root.left) self.invertTree(root.right) return root填充二叉树节点的右侧指针
def connect(root): if root is None: return None connectTwoNode(root.left,root.right) return root def connectTwoNode(node1,node2): if (node1 is None) or (node2 is None): return node1.next = node2 connectTwoNode(node1.left,node1.right) connectTwoNode(node2.left,node2.right) connectTwoNode(node1.right,node2.left)二叉树展开为链表
def flatten(root): if root is None: return None flatten(root.left) flatten(root.right) left = root.left right = root.right root.left = None root.right = left p = root while p.right is not None: p = p.right p.right = right构造最大二叉树
#超过递归深度 def constructMaximumBinaryTree(nums): return build(nums, 0, nums.length - 1) def build(nums, lo , hi): if lo > hi: return None index = -1 maxVal = float("-inf") for i in range(lo,hi+1): if maxVal < nums[i]: maxVal = nums[i] index = i root = TreeNode(maxVal) root.left = build(nums,lo,index-1) root.right = build(nums,index+1,hi) return root通过前序和中序遍历结果构造二叉树
def buildTree(preorder,inorder): return build(preorder,0,len(preorder)-1,inorder,0,len(inorder)-1) def build(preorder,preStart,preEnd,inorder,inStart,inEnd): if preStart > preEnd: return None rootVal = preorder[preStart] index = 0 for i in range(inStart,inEnd+1): if inorder[i] == rootVal: index = i break root = TreeNode(rootVal) leftSize = index - inStart root.left = build(preorder,preStart+1,preStart+leftSize,inorder,inStart,index-1) root.right = build(preorder,preStart+leftSize+1,preEnd,inorder,index+1,inEnd) return root通过中序和后序遍历结果构造二叉树
class TreeNode: def __init__(self,val=0,left=None,right=None): self.val = val self.left = left self.right = right def buildTree(inorder,postorder): def build(inorder,instart,inend,postorder,poststart,postend): if instart > inend: return None rootValue = postorder[postend] for i in range(instart,inend+1): if inorder[i] == rootValue: index = i break root = TreeNode(rootValue) leftSize = index-instart root.left = build(inorder,instart,index-1,postorder,poststart,poststart+leftSize-1) root.right = build(inorder,index+1,inend,postorder,poststart+leftSize,postend-1) return root return build(inorder,0,len(inorder)-1,postorder,0,len(postorder)-1)寻找重复子树
class treeNode(): def __init__(self,val=0,left=None,right=None): self.val = val self.left = left self.right = right class Solution: def findDuplicateSubtrees(self, root: Optional[TreeNode]) -> ist[Optional[TreeNode]]: def traverse(root): if root is None: return None left = traverse(root.left) right = traverse(root.right) subTree = str(left) + "," + str(right)+ "," + str(root.val) fre = subTree_fre.setdefault(subTree,0) if fre == 1: res.append(root) subTree_fre[subTree] = fre + 1 return subTree res = [] subTree_fre = dict() traverse(root) return res二叉树的序列化与反序列化 前序遍历
class Codec: def serialize(self,root): if root is None: return "None" return str(root.val)+","+str(self.serialize(root.left))+","+str(self.serialize(root.right)) def deserialize(self,data): def dfs(datalist): data = datalist.pop(0) if data == "None": return None root = TreeNode(int(data)) root.left = dfs(datalist) root.right = dfs(datalist) return root datalist = data.split(",") return dfs(datalist)
- 中序遍历无法实现反序列化
class Codec: def serialize(self,root): if root is None: return "" queue = collections.deque([root]) res = [] while queue: node = queue.popleft() if node is None: res.append("None") continue res.append(str(node.val)) queue.append(node.left) queue.append(node.right) return ",".join(res) def deserialize(self,data): if not data: return [] dataList = data.split(",") root = TreeNode(int(dataList[0])) queue = collections.deque(root) i = 1 while queue: node = queue.popleft() if dataList[i] != "None": node.left = TreeNode(int(dataList[i])) queue.append(node.left) i += 1 if dataList[i] != "None": node.right = TreeNode(int(data)) queue.append(node.right) i += 1 return root扁平化嵌套列表迭代器
class NestedIterator: def __init__(self,nestedList): self.q = collections.deque() self.dfs(nestedList) def dfs(self,nestedList): for elem in nestedList: if elem.isInteger(): self.q.append(elem.getInteger()) else: self.dfs(elem.getList()) def next(self): return self.q.popleft() def hasNext(self): return len(self.q)二叉树的最近公共祖先LCA
def lowestCommonAncestor(root,p,q): if root is None: return None if (root == p) or (root == q): return root left = lowestCommonAncestor(root.left,p,q) right = lowestCommonAncestor(root.right,p,q) if (left is not None) and (right is not None): return root if (left is None) and (right is None): return None return right if left is None else left完全二叉树的节点个数
完全二叉树:
满二叉树:
#普通二叉树,时间复杂度O(N) def countNodes(root): if root is None: return 0 return 1 + countNodes(root.left) + countNodes(root.right) #满二叉树,节点总数和树的高度呈指数关系 def countNodes(root): h = 0 while root: root = root.left h += 1 return pow(2,h) - 1 #完全二叉树,时间复杂度O(logN*logN) def countNodes(root): if root is None: return 0 l = root r = root hl = 0 hr = 0 while l: l = l.left hl += 1 while r: r = r.right hr += 1 if hl == hr: return pow(2,hl) - 1 return 1 + countNodes(root.left) + countNodes(root.right)
- 由于完全二叉树的性质,其子树一定有一棵是满的
stk = collections.deque() #左侧遍历到底,存入栈 def pushLeftBranch(p): while p: #前序遍历代码位置 stk.append(p) p = p.left def traverse(root): visited = TreeNode(-1) #指向上一次遍历完的子树根节点 pushLeftBranch(root) while stk: p = stk[-1] if ((p.left is None) or (p.left == visited)) and (p.right != visited): #中序遍历代码位置 pushLeftBranch(p.right) if (p.right is None) or (p.right == visited): #后序遍历代码位置 visited = stk.pop(-1)
- 除了BFS层级遍历外,二叉树还是用递归,因为递归最符合二叉树结构他点
-
BST特点:
1、对于BST的每个节点node,左子树节点的值 < node的值 < 右子树节点的值
2、对于BST的每个节点node,左子树和右子树都是BST
3、BST的中序遍历结果是有序的(升序)
class Solution: def kthSmallest(self, root: Optional[TreeNode], k: int) -> int: self.res = 0 self.rank = 0 self.traverse(root,k) return self.res def traverse(self,root,k): if root is None: return None self.traverse(root.left,k) self.rank += 1 if self.rank == k: self.res = root.val return self.traverse(root.right,k)BST转化累加树
class Solution(): def convertTree(root): def convert(root): if root is None: return None convert(root.right) self.sum += root.val root.val = self.sum convert(root.left) self.sum = 0 convert(root) return root判断BST合法性
def isValidBST(root): return isValidBST(root,None,None) def isValidBST(root,min,max): if root is None: return True if min is not None and root.val <= min.val: return False if max is not None and root.val >= max.val: return False return isValidBST(root.left,min,root) and isValidBST(root.right,root,max)在BST中搜索元素
def search(root,val): if root is None: return None if val > root.val: return search(root.right,val) if val < root.val: return search(root.left,val) return root在BST中插入一个数
def insertIntoBST(root,val): if root is None: return TreeNode(val) if val > root.val: root.right = insertIntoBST(root.right,val) if val < root.val: root.left = insertIntoBST(root.left,val) return root在BST中删除一个数
class Solution: def deleteNode(self, root: Optional[TreeNode], key: int) -> Optional[TreeNode]: def getMin(root): while root.left is not None: root = root.left return root if root is None: return None if root.val == key: if root.left is None: return root.right elif root.right is None: return root.left minNode = getMin(root.right) minNode.left = root.left minNode.right = root.right root = minNode elif root.val < key: self.deleteNode(root.right,key) else: self.deleteNode(root.left,key) return root不同的二叉搜索树
class Solution: def numTrees(self, n: int) -> int: memo = [[0 for i in range(n+1)] for j in range(n+1)] return count(1,n,memo) def count(lo,hi,memo): if lo > hi: return 1 if memo[lo][hi] != 0: return memo[lo][hi] res = 0 for i in range(lo,hi+1): left = count(lo,i-1,memo) right = count(i+1,hi,memo) res += left * right memo[lo][hi] = res return res不同的二叉搜索树②
def generateTrees(n): if n == 0: return TreeNode() return build(1,n) def build(lo,hi): res = [] if lo > hi: return r[None] for i in range(lo,hi+1): leftTree = build(lo,i-1) rightTree = build(i+1,hi) for left in leftTree: for right in rightTree: root = TreeNode(i) root.left = left root.right = right res.append(root) return res二叉搜索子树的最大键值和
import sys sum = 0 def maxSumBST(root): traverse(root) return maxSum def traverse(root): #返回[isBST,min,max,sum] if root is None: return [1,sys.maxsize,-sys.maxsize-1,0] left = traverse(root.left) right = traverse(root.right) res = [0 for i in range(4)] if (left[0] == 1) and (right[0] == 1) and (left[2] < root.val < right[1]): #以root为根的二叉树是BST res[0] = 1 res[1] = min(left[1],root.val) res[2] = max(right[2],root.val) res[3] = left[3] + right[3] + root.val maxSum = max(maxSum,res[3]) else: res[0] = 0 return res
- BST相关问题:(1)利用BST左小右大的特性提升算法效率;(2)中序遍历的特性(有序)满足题目要求
- 如果当前节点要做的事情需要通过左右子树的计算结果推导出来,就要用到后序遍历
- 要尽可能避免递归函数中调用其他递归函数
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)