代码随想录算法训练营第十八天|513. 找树左下角的值、112. 路径总和、113. 路径总和 II、106. 从中序与后序遍历序列构造二叉树、105. 从前序与中序遍历序列构造二叉树
513. 找树左下角的值
【注意】
1.用递归的话就就一直向左遍历,但是到最后一个,它未必是最后一行。是要找到树的最后一行的最左边的值。(不一定是指是左孩子)
2.如果使用递归法,如何判断是最后一行呢,其实就是深度最大的叶子节点一定是最后一行。
3.只要是优先遍历左都可以,所以前中后序都可。
4.层序遍历只需要记录最后一行的第一个节点的数值即可。
【代码】
1.递归遍历中,用一个变量存储最大深度。终止条件:遍历到叶子节点。然后比较当前叶子节点的深度是否比记录最大深度还大,大的话就要更新这个变量。result变量中存储遍历完树最后的最大深度。
2.向左遍历时先判断root.left是否为空,要有回溯过程,要不depth一直在增加,就出现错误。traversal(root.left,depth+1),隐藏回溯的过程在这个递归函数中,depth+1没有改变depth的值。
3.没有中的处理逻辑,只要强调左在右前面就行。
【代码】
1 # Definition for a binary tree node. 2 # class TreeNode(object): 3 # def __init__(self, val=0, left=None, right=None): 4 # self.val = val 5 # self.left = left 6 # self.right = right 7 from collections import deque 8 class Solution(object): 9 def findBottomLeftValue(self, root): 10 """ 11 :type root: TreeNode 12 :rtype: int 13 """ 14 # #1.递归法+回溯 15 # self.max_depth = float('-inf') 16 # self.result = None #最后左下角的值 17 # self.traversal(root,0) #递归 18 19 # return self.result 20 21 # def traversal(self, node, depth): 22 # if not node.left and not node.right:#迭代终止条件:达到叶子节点 23 # if depth > self.max_depth: 24 # self.max_depth = depth 25 # self.result = node.val #因为是先遍历最大深度的左节点所以保证result保存的是左下角的值 26 # return 27 28 # #左 29 # if node.left:#不为空时 30 # depth += 1 31 # self.traversal(node.left, depth) 32 # depth -= 1#回溯 33 # #右 34 # if node.right: 35 # depth += 1 36 # self.traversal(node.right, depth) 37 # depth -= 1 38 39 #2.迭代法:队列 #测试用例[1,2,3,4,null,5,6,null,null,7] 40 queue = deque([root]) 41 while queue: 42 size = len(queue) #1->2->3->1 43 leftmost = queue[0].val #1->2->4->7 44 45 for i in range(size): #1->2->3 46 node = queue.popleft() #1->2->3->4->5->6 47 if node.left: #2->4->5->7 48 queue.append(node.left) #2->34->45->67 49 if node.right: #3->6 50 queue.append(node.right) #23->456 51 if not queue: 52 return leftmost #7
112. 路径总和
【注意】
1.本题前中后序都可以,无所谓,因为中节点也没有处理逻辑。
2.只要找到一条符合的路径就返回,返回true。参数直接传入目标值,做累减,知道叶子节点时为0,就是要求得的路径。
3.终止条件:遇到叶子节点进行判读是否为0.
【代码】
1 # Definition for a binary tree node. 2 # class TreeNode(object): 3 # def __init__(self, val=0, left=None, right=None): 4 # self.val = val 5 # self.left = left 6 # self.right = right 7 class Solution(object): 8 def hasPathSum(self, root, targetSum): 9 """ 10 :type root: TreeNode 11 :type targetSum: int 12 :rtype: bool 13 """ 14 if not root: 15 return False 16 return self.traversal(root, targetSum) #递归 17 #1.递归+回溯 18 def traversal(self, node, count): 19 # 遇到叶子节点,并且计数为0 20 if not node.left and not node.right and count==0: 21 return True 22 if not node.left and not node.right and count!=0: 23 return False 24 25 #左 26 if node.left: 27 count -= node.left.val 28 if self.traversal(node.right, count): 29 return True 30 count += node.left.val #回溯 31 # 右 32 if node.right: 33 count -= node.right.val 34 if self.traversal(node.right, count): # 递归,处理节点 35 return True 36 count += node.right.val # 回溯,撤销处理结果 37 38 return False
113. 路径总和 II
【代码】
1 # Definition for a binary tree node. 2 # class TreeNode(object): 3 # def __init__(self, val=0, left=None, right=None): 4 # self.val = val 5 # self.left = left 6 # self.right = right 7 class Solution(object): 8 def __init__(self): 9 self.result = [] 10 self.path = [] 11 #1.递归+回溯 12 def traversal(self, node, count): 13 if not node.left and not node.right and count == 0: # 遇到了叶子节点且找到了和为sum的路径 14 self.result.append(self.path[:]) 15 return 16 if not node.left and not node.right and count != 0: # 遇到叶子节点而没有找到合适的边,直接返回 17 return 18 #左 19 if node.left: 20 self.path.append(node.left.val) 21 count -= node.left.val 22 self.traversal(node.left, count) 23 count += node.left.val#回溯 24 self.path.pop() 25 26 #右 27 if node.right: 28 self.path.append(node.right.val) 29 count -= node.right.val 30 self.traversal(node.right, count) # 递归 31 count += node.right.val # 回溯 32 self.path.pop() # 回溯 33 34 def pathSum(self, root, targetSum): 35 """ 36 :type root: TreeNode 37 :type targetSum: int 38 :rtype: List[List[int]] 39 """ 40 if not root: 41 return self.result 42 self.path.append(root.val)# 把根节点放进路径 43 self.traversal(root,targetSum-root.val) 44 45 return self.result
106. 从中序与后序遍历序列构造二叉树
【注意】
1.以 后序数组的最后一个元素为切割点,先切中序数组,根据中序数组,反过来再切后序数组。一层一层切下去,每次后序数组最后一个元素就是节点元素。
【代码】
说到一层一层切割,就应该想到了递归。
来看一下一共分几步:
-
第一步:如果数组大小为零的话,说明是空节点了。
-
第二步:如果不为空,那么取后序数组最后一个元素作为节点元素。
-
第三步:找到后序数组最后一个元素在中序数组的位置,作为切割点
-
第四步:切割中序数组,切成中序左数组和中序右数组 (顺序别搞反了,一定是先切中序数组)
-
第五步:切割后序数组,切成后序左数组和后序右数组
-
第六步:递归处理左区间和右区间
# Definition for a binary tree node. # class TreeNode(object): # def __init__(self, val=0, left=None, right=None): # self.val = val # self.left = left # self.right = right class Solution(object): def buildTree(self, inorder, postorder): """ :type inorder: List[int] :type postorder: List[int] :rtype: TreeNode """ # 第一步: 特殊情况讨论: 树为空. (递归终止条件) if not postorder: return None # 第二步: 后序遍历的最后一个就是当前的中间节点. root_val = postorder[-1] root = TreeNode(root_val) #根节点 # 第三步: 找切割点. separator_idx = inorder.index(root_val) # 第四步: 切割inorder数组. 得到inorder数组的左,右半边. 左闭右开 inorder_left = inorder[:separator_idx] inorder_right = inorder[separator_idx+1:] # 第五步: 切割postorder数组. 得到postorder数组的左,右半边. # ⭐️ 重点1: 中序数组大小一定跟后序数组大小是相同的. #左闭右开 右开包含下一个区间的一个值 postorder_left = postorder[:len(inorder_left)] #控制大小一样,用len postorder_right = postorder[len(inorder_left):len(postorder)-1] # 第六步: 递归 root.left = self.buildTree(inorder_left,postorder_left) root.right = self.buildTree(inorder_right,postorder_right) return root
105. 从前序与中序遍历序列构造二叉树
【代码】
1 # Definition for a binary tree node. 2 # class TreeNode(object): 3 # def __init__(self, val=0, left=None, right=None): 4 # self.val = val 5 # self.left = left 6 # self.right = right 7 class Solution(object): 8 def buildTree(self, preorder, inorder): 9 """ 10 :type preorder: List[int] 11 :type inorder: List[int] 12 :rtype: TreeNode 13 """ 14 # 第一步: 特殊情况讨论: 树为空. 或者说是递归终止条件 15 if not preorder: 16 return None 17 18 # 第二步: 前序遍历的第一个就是当前的中间节点. 19 root_val = preorder[0] 20 root =TreeNode(root_val) 21 22 # 第三步: 找切割点. 23 separator_idx = inorder.index(root_val) 24 25 # 第四步: 切割inorder数组. 得到inorder数组的左,右半边. 26 inorder_left = inorder[:separator_idx] 27 inorder_right = inorder[separator_idx+1:] 28 29 # 第五步: 切割preorder数组. 得到preorder数组的左,右半边. 30 # ⭐️ 重点1: 中序数组大小一定跟前序数组大小是相同的. 31 preorder_left = preorder[1:1+len(inorder_left)] 32 preorder_right = preorder[1+len(inorder_left):] 33 34 # 第六步: 递归 35 root.left = self.buildTree(preorder_left,inorder_left) 36 root.right = self.buildTree(preorder_right,inorder_right) 37 38 return root
浙公网安备 33010602011771号