目录
一、树与二叉树的基本知识、二叉树的遍历
二、0144.二叉树的前序遍历
题目:
给你二叉树的根节点 root ,返回它节点值的 前序 遍历。
示例:
输入:root = [1,null,2,3]
输出:[1,2,3]
思路1:
采用递归的方法来实现前序遍历。
先遍历根节点,在遍历左子节点,最后遍历右子节点。
class Solution:
def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
order = []
def perorder(root):
if not root:
return
order.append(root.val)
perorder(root.left)
perorder(root.right)
perorder(root)
return order
思路2:
采用迭代的方式来实现,即使用显示栈。
class Solution:
def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
order = []
stack = [root]
while root and stack:
node = stack.pop()
order.append(node.val)
if node.right:
stack.append(node.right)
if node.left:
stack.append(node.left)
return order
还有一种方法,通过morris遍历,可实现 O ( 1 ) O(1) O(1)的空间复杂度。
三、94. 二叉树的中序遍历
题目:
给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。
示例:
输入:root = [1,null,2,3]
输出:[1,3,2]
思路1:
采用递归的方法进行求解:
先遍历左子树,再访问根节点,最后访问右子树。
class Solution:
def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
order = []
def inorder(root):
if not root:
return
inorder(root.left)
order.append(root.val)
inorder(root.right)
inorder(root)
return order
思路2:
采用迭代的方法求解,同样使用显示栈。
class Solution:
def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
if not root:
return []
order = []
stack = []
while stack or root:
while root:
stack.append(root)
root = root.left
node = stack.pop()
order.append(node.val)
root = node.right
return order
四、0145. 二叉树的后序遍历
题目:
给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历 。
示例:
输入:root = [1,null,2,3]
输出:[3,2,1]
思路1:
采用递归的方法求解。
先遍历左子树,再遍历右子树,最后访问根节点。
class Solution:
def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
order = []
def postorder(root):
if not root:
return
postorder(root.left)
postorder(root.right)
order.append(root.val)
postorder(root)
return order
思路2:
采用迭代的方法,即显示栈实现。
class Solution:
def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
order = []
stack = []
prev = None
while root or stack:
while root:
stack.append(root)
root = root.left
node = stack.pop()
if node.right == prev or not node.right:
order.append(node.val)
prev = node
root = None
else:
stack.append(node)
root = node.right
return order
五、102. 二叉树的层序遍历
题目:
给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。
示例:
输入:root = [3,9,20,null,null,15,7]
输出:[[3],[9,20],[15,7]]
思路:
使用队列来模拟层序遍历。
class Solution:
def levelOrder(self, root: TreeNode) -> List[List[int]]:
if not root:
return []
queue = [root]
order = []
while queue:
order1 = []
size = len(queue)
for _ in range(size):
node = queue.pop(0)
order1.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
order.append(order1)
return order
六、105.从前序与中序遍历序列构造二叉树
题目:
给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。
示例:
输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]
思路:
从前序遍历序列可以知道根节点,再根据中序遍历序列就可以知道左子序列和右子序列的集合。
采用递归实现即可。
class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
def creatTree(preorder,inorder,n):
if n == 0:
return None
k = 0
while preorder[0] != inorder[k]:
k += 1
node = TreeNode(inorder[k])
node.left = creatTree(preorder[1:k+1],inorder[0:k],k)
node.right = creatTree(preorder[k+1:],inorder[k+1:],n-k-1)
return node
return creatTree(preorder,inorder,len(inorder))
七、106. 从中序与后序遍历序列构造二叉树
题目:
给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。
示例:
输入:inorder = [9,3,15,20,7], postorder = [9,15,7,20,3]
输出:[3,9,20,null,null,15,7]
思路:
从后序遍历序列的最后一个可以知道根节点,同理将该节点代入到中序遍历序列中进行查找,即可得到左子序列和右子序列。
采用递归实现即可。
class Solution:
def buildTree(self, inorder: List[int], postorder: List[int]) -> TreeNode:
def creatTree(inorder,postorder,n):
if n == 0:
return None
k = 0
while postorder[n-1] != inorder[k]:
k += 1
node = TreeNode(inorder[k])
node.left = creatTree(inorder[0:k],postorder[0:k],k)
node.right = creatTree(inorder[k+1:],postorder[k:n-1],n-1-k)
return node
return creatTree(inorder,postorder,len(inorder))
八、889. 根据前序和后序遍历构造二叉树
题目:
给定两个整数数组,preorder 和 postorder ,其中 preorder 是一个具有 无重复 值的二叉树的前序遍历,postorder 是同一棵树的后序遍历,重构并返回二叉树。
如果存在多个答案,您可以返回其中 任何 一个。
示例:
输入:preorder = [1,2,4,5,3,6,7], postorder = [4,5,2,6,7,3,1]
输出:[1,2,3,4,5,6,7]
思路:
前序遍历的顺序是:根节点-左子树-右子树;
后序遍历的顺序是:左子树-右子树-根节点。
因此,可以假设前序遍历的第二个元素为后序遍历中左子树遍历的最后一个节点,并区分左右子树序列。
分出左右子树序列后,就可以使用递归实现。
class Solution:
def constructFromPrePost(self, preorder: List[int], postorder: List[int]) -> TreeNode:
def creatTree(preorder,postorder,n):
if n == 0:
return None
node = TreeNode(preorder[0])
if n == 1:
return node
k = 0
while preorder[1] != postorder[k]:
k += 1
node.left = creatTree(preorder[1:k+2],postorder[0:k+1],k+1)
node.right = creatTree(preorder[k+2:],postorder[k+1:-1],n-k-2)
return node
return creatTree(preorder,postorder,len(preorder))
九、二叉搜索树
十、700. 二叉搜索树中的搜索
题目:
给定二叉搜索树(BST)的根节点 root 和一个整数值 val。
你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 null 。
示例:
输入:root = [4,2,7,1,3], val = 2
输出:[2,1,3]
思路:
直接按二叉搜索树的规则搜索即可。
class Solution:
def searchBST(self, root: TreeNode, val: int) -> TreeNode:
if not root:
return None
while root:
if root.val > val:
root = root.left
elif root.val < val:
root = root.right
else:
return root
return None
十一、701. 二叉搜索树中的插入操作
题目:
给定二叉搜索树(BST)的根节点 root 和要插入树中的值 value ,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。
注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回 任意有效的结果 。
示例:
输入:root = [4,2,7,1,3], val = 5
输出:[4,2,7,1,3,5]
思路:
先进行二叉搜索,当搜到对应位置时插入节点即可。
class Solution:
def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode:
if not root:
return TreeNode(val)
cur = root
while cur:
if cur.val > val:
if not cur.left:
cur.left = TreeNode(val)
break
else:
cur = cur.left
else:
if not cur.right:
cur.right = TreeNode(val)
break
else:
cur = cur.right
return root
十二、450. 删除二叉搜索树中的节点
题目:
给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。
一般来说,删除节点可分为两个步骤:
首先找到需要删除的节点;
如果找到了,删除它。
示例:
输入:root = [5,3,6,2,4,null,7], key = 3
输出:[5,4,6,2,null,null,7]
解释:给定需要删除的节点值是 3,所以我们首先找到 3 这个节点,然后删除它。
一个正确的答案是 [5,4,6,2,null,null,7], 如下图所示。
另一个正确答案是 [5,2,6,null,4,null,7]。
思路:
先二分搜索,再删除。
class Solution:
def deleteNode(self, root: Optional[TreeNode], key: int) -> Optional[TreeNode]:
if not root:
return root
if root.val > key:
root.left = self.deleteNode(root.left,key)
return root
elif root.val < key:
root.right = self.deleteNode(root.right,key)
return root
else:
if not root.left:
return root.right
elif not root.right:
return root.left
else:
cur = root.right
while cur.left:
cur = cur.left
cur.left = root.left
return root.right
十三、98. 验证二叉搜索树
题目:
给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。
有效 二叉搜索树定义如下:
节点的左子树只包含 小于 当前节点的数。
节点的右子树只包含 大于 当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。
示例:
输入:root = [2,1,3]
输出:true
思路:
递归求解,不断判断左右子树是否也是一个二叉搜索树。
class Solution:
def isValidBST(self, root: Optional[TreeNode]) -> bool:
def helper(root,min_v,max_v):
if not root:
return True
if root.val<=min_v or root.val>=max_v:
return False
return helper(root.left,min_v,root.val) and helper(root.right,root.val,max_v)
return helper(root,float('-inf'),float('inf'))