目录
Leetcode - 654
这题和104 105通过前中后序构建二叉树的套路是一样的,
递归条件终止条件:序列为空返回None
先求一个最大值节点作为根节点,查找根节点的位置,对序列进行划分,划分为左右子树,分别对左右子树递归,最后返回根节点
def constructMaximumBinaryTree(self, nums: List[int]) -> Optional[TreeNode]:
def constructTree(nums):
if nums == []:
return None
rootVal = max(nums)
root = TreeNode(rootVal)
index = nums.index(rootVal)
leftChild = nums[:index]
rightChild = nums[index+1:]
root.left = constructTree(leftChild)
root.right = constructTree(rightChild)
return root
return constructTree(nums)
Leetcode - 617
这题使用先序遍历更符合逻辑,关键就在于确定递归的终止条件,首先要明确地是,两棵树是同时进行遍历的,遍历到的节点是同步的,对节点分为三种情况讨论:1. 第一棵树对应的该节点为空 2.第二棵树对应的该节点为空 3. 两个节点均不为空。
针对1,2情况 写出递归终止:如果第一棵树节点为空,返回第二棵树相应的节点。如果第二棵树节点为空,返回第一棵树相应的节点。这里其实包含了左右两树相应节点均为空的情况,若同时为空则返回None,以上条件是囊括了这种情况
当同时不为空时,又分两种写法,第一种是打算直接以第一棵树作为结果返回的,此处直接对第一棵树的节点的val做加法即可。此处完成了“中”,接着进行“左右”,注意此处左右遍历后的结果分别作为第一棵树的左子树和右子树
def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]:
def merge(root1,root2):
if not root1:
return root2
if not root2:
return root1
root1.val += root2.val
root1.left = merge(root1.left,root2.left)
root1.right = merge(root1.right,root2.right)
return root1
return merge(root1,root2)
第二种写法是新定义一颗树
def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]:
def merge(root1,root2):
if not root1:
return root2
if not root2:
return root1
root1.val += root2.val
root1.left = merge(root1.left,root2.left)
root1.right = merge(root1.right,root2.right)
return root1
return merge(root1,root2)
Leetcode - 700
直接while循环遍历,到节点为空前还没找到就返回False
def searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
while root:
if root.val == val:
return root
elif root.val < val:
root = root.right
else:
root = root.left
else:
return None
递归写法:
终止条件是重点:两个 若节点到None,代表没找到,返回None,也就是返回root,另一种是找到了 返回root
若当前节点值大于target,则遍历左子树,否则遍历右子树
def searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
def search(root,val):
if not root or root.val == val:
return root
if root.val > val:
return self.searchBST(root.left, val)
else:
return self.searchBST(root.right, val)
return search(root,val)
Leetcode - 98
由于二叉搜索树,在进行中序遍历的时候,得出的序列是有序的,所以可以先得出中序遍历的序列再判断是否有序即可,注意 遇到二叉搜索树 就考虑中序
def isValidBST(self, root: Optional[TreeNode]) -> bool:
#中序遍历
res =[]
def traversal(node):
if node == None:
return
traversal(node.left)
res.append(node.val)
traversal(node.right)
traversal(root)
#判断序列是否有序
i =0
j =i+1
while j <len(res):
if res[j] <= res[i]:
return False
else:
i+=1
j+=1
else:
return True
递归的做法,首先定义一个全局变量 maxValue 初始化为-float("INF"),
终止条件为节点为空,此处是return True因为空树满足任何树的定义,空树也是二叉搜索树
这里依然是中序,先是左子树,返回一个bool值,在就是中间,因为是有序的,所以当前节点的值大于maxValue才合理,接着跟新maxValue为当前值,否则返回False,再就是右子树,要同时满足左右子树均为二叉搜索树才行
def isValidBST(self, root: Optional[TreeNode]) -> bool:
maxValue = -float("INF")
def check(root):
nonlocal maxValue
if not root:
return True
checkLeft = check(root.left)
if maxValue < root.val:
maxValue = root.val
else:
return False
checkRight = check(root.right)
return checkLeft and checkRight
return check(root)
此外,这里可以不用跟新最大值的方法,可以使用双指针,利用一个指针指向上一个节点,先初始化一个指针为None,再每一轮中序遍历中,将root赋值给这个指针,那么在每一轮赋值之前,这个指针都指向上一个节点,通过上一个节点的值与当前root的值判断即可,保证上一个节点值小于当前root,否则返回False
def isValidBST(self, root: Optional[TreeNode]) -> bool:
# maxValue = -float("INF")
node = None
def check(root):
nonlocal node
if not root:
return True
checkLeft = check(root.left)
if node!=None:
if node.val >= root.val:
return False
node = root
checkRight = check(root.right)
return checkLeft and checkRight
return check(root)