文章目录
- [513. 找树左下角的值](https://leetcode.cn/problems/find-bottom-left-tree-value/description/)
- [112. 路径总和](https://leetcode.cn/problems/path-sum/description/)
- [113. 路径总和 II](https://leetcode.cn/problems/path-sum-ii/description/)
- [106. 从中序与后序遍历序列构造二叉树](https://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal/description/)
- 105.从前序与中序遍历序列构造二叉树
513. 找树左下角的值
迭代
用层序遍历的方式的话就是输出最后一层的一个结点的值
class Solution:
def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
queue = collections.deque([root])
ans = 0
while queue:
for i in range(len(queue)):
cur = queue.popleft()
if i == 0:
ans = cur.val
if cur.left:
queue.append(cur.left)
if cur.right:
queue.append(cur.right)
return ans
递归
如果按照前序遍历的方式来进行遍历,那么第一次使得深度大于最大深度的叶子结点就是当前子树的最后一层的最左边的结点。因此在迭代的时候需要知道当前深度与最大深度进行比较,如果结点是叶子结点,并且深度大于最大深度就保存下当前的深度和叶子结点的值。
递归的终止条件就是为叶子结点,并且深度大于最大深度时。否则看结点时候有左结点,有的话则深度+1左结点进入递归,递归结束后深度需要-1,右结点同理。
class Solution:
def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
self.max_dep = -1
self.result = 0
self.findLeft(root, 0)
return self.result
def findLeft(self, root, depth):
if root.right == None and root.left == None:
if depth>self.max_dep:
self.max_dep = depth
self.result = root.val
return
if root.left:
depth += 1
self.findLeft(root.left, depth)
depth -= 1
if root.right:
depth += 1
self.findLeft(root.right, depth)
depth -= 1
112. 路径总和
递归
因为只需要找到一个符合要求的路径就返回True,所以不需要遍历所有的根节点到叶子节点的路径,只需要按照前序遍历的方式来寻找到叶子路径,判断是否路径和满足条件,如果不满足则对存在的左右结点再进入递归判断。
class Solution:
def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
if not root:
return False
targetSum -= root.val
if root.left==None and root.right==None and targetSum==0:
return True
if root.left:
if self.hasPathSum(root.left, targetSum):
return True
if root.right:
if self.hasPathSum(root.right, targetSum):
return True
return False
113. 路径总和 II
在上一题的基础上把满足条件的路径保存下来就行了
class Solution:
def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
if not root:
return []
path = [root.val]
result = []
self.digpath(root, targetSum-root.val, path, result)
return result
def digpath(self, root, count, path, result):
if root.left==None and root.right==None and count==0:
result.append(path[:])
return
if root.left:
path.append(root.left.val)
count -= root.left.val
self.digpath(root.left, count, path, result)
path.pop()
count += root.left.val
if root.right:
path.append(root.right.val)
count -= root.right.val
self.digpath(root.right, count, path, result)
path.pop()
count += root.right.val
106. 从中序与后序遍历序列构造二叉树
在中序遍历的数组里面看不出任何顺序,但是后序遍历里面,最后一个元素一定是当前子树的根节点。找到当前子树的根节点之后,就可以根据这个值在中序遍历里面找到左右子树的切分区,又因为左右子树的大小是一样的,所以根据中序遍历的切分又可以把后序遍历的数组也切分了,这样就又化为对左右两个子树的一次递归。
递归的时候返回条件一个是当后序遍历的数组为空,则返回None,如果后序数组pop完根节点之后为空,则直接返回这个根节点。然后进到中序遍历的数组中寻找导这个根节点的位置,按照这个位置切分中序和后序遍历的数组,令当前节点的左子树进入递归,右子树也进入递归,最后返回根节点。
class Solution:
def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
if not postorder:
return None
cur = TreeNode(postorder.pop())
if not postorder:
return cur
for i in range(len(inorder)):
if inorder[i] == cur.val:
break
cur.left = self.buildTree(inorder[:i], postorder[:i])
cur.right = self.buildTree(inorder[i+1:], postorder[i:])
return cur
105.从前序与中序遍历序列构造二叉树
一样的,前序从头拿根节点。
class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
if not preorder:
return None
cur = TreeNode(preorder[0])
if len(preorder)==1:
return cur
for i in range(len(inorder)):
if inorder[i] == cur.val:
break
cur.left = self.buildTree(preorder[1:i+1], inorder[:i])
cur.right = self.buildTree(preorder[i+1:], inorder[i+1:])
return cur