代码随想录算法训练营第18天|二叉树part05|513.找树左下角的值、路径总和、从中序与后序遍历序列构造二叉树

代码随想录算法训练营第18天|二叉树part05|513.找树左下角的值、路径总和、从中序与后序遍历序列构造二叉树

513.找树左下角的值

513.找树左下角的值

自己做

思路:

最底层、最左边

层次遍历

返回result[-1][0]就是

代码:

python

# 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 findBottomLeftValue(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root: 
            return -1

        queue = deque()
        queue.append(root)

        result = []

        while len(queue):
            level = []
            for _ in range(len(queue)):
                cur = queue.popleft()
                level.append(cur.val)
                if cur.left: queue.append(cur.left)
                if cur.right: queue.append(cur.right)

            result.append(level)

        return result[-1][0]

路径总和

112. 路径总和

112. 路径总和

自己做

思路:

我知道本题使用回溯法来做,但是再判断完是否curSum==targetSum后,在递归中,如何返回这个bool类型的值到原函数中呢?卡在了这里

代码:

python(看完讲解自己编写)

# 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 hasPathSum(self, root, targetSum):
        """
        :type root: TreeNode
        :type targetSum: int
        :rtype: bool
        """
        # dequeue = deque() # 用于存放从根结点到当前结点走过的路径

        if not root:
            return False
        
        curSum = 0 # 用于存放从很结点到当前结点的累加和
        
        curSum += root.val

        return self.helper(root, curSum, targetSum)

    def helper(self, root, curSum, targetSum):# 1. 
        # 2. 
        if not root.left and not root.right and curSum == targetSum:
            return True 
        if not root.left and not root.right:
            return False

        # 3.
        if root.left:
            curSum += root.left.val
            if self.helper(root.left, curSum, targetSum): return True 
            curSum -= root.left.val
        
        if root.right:
            curSum += root.right.val
            if self.helper(root.right, curSum, targetSum): return True 
            curSum -= root.right.val
        
        return False

代码随想录

思路:

相信很多同学都会疑惑,递归函数什么时候要有返回值,什么时候没有返回值,特别是有的时候递归函数返回类型为bool类型。

递归函数什么时候需要返回值?什么时候不需要返回值?这里总结如下三点:

  • 如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值。(这种情况就是本文下半部分介绍的113.路径总和ii)

  • 如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返回值。 (这种情况我们在236. 二叉树的最近公共祖先 (opens new window)中介绍)

  • 如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回。(本题的情况)

递归处理

只要找到一条符合条件的路径,就要及时返回,不再递归下去, 一直返回到出递归

怎么才能从叶子结点如果为True的话就一直返回到出递归呢?

if not root.left and not root.right and curSum == targetSum:
  		return True

# 意思就是只要返回值为True, 就不再递归下去,直接出递归
if self.helper(root.left) : return true
if self.helper(root.right) : return true

代码:

python

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
	# 1 确定递归函数的参数和返回类型
    def traversal(self, cur: TreeNode, count: int) -> bool:
    	# 2. 确定终止条件
        if not cur.left and not cur.right and count == 0: # 遇到叶子节点,并且计数为0
            return True
        if not cur.left and not cur.right: # 遇到叶子节点直接返回
            return False
        
        # 3. 确定单层递归的逻辑
        if cur.left: # 左
            count -= cur.left.val
            if self.traversal(cur.left, count): # 递归,处理节点
                return True # 只要为True,就不再递归下去,就返回了
            count += cur.left.val # 回溯,撤销处理结果
            
        if cur.right: # 右
            count -= cur.right.val
            if self.traversal(cur.right, count): # 递归,处理节点
                return True
            count += cur.right.val # 回溯,撤销处理结果
            
        return False
    
    def hasPathSum(self, root: TreeNode, sum: int) -> bool:
        if root is None:
            return False
        return self.traversal(root, sum - root.val)      

迭代

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def hasPathSum(self, root: TreeNode, sum: int) -> bool:
        if not root:
            return False
        # 此时栈里要放的是pair<节点指针,路径数值>
        st = [(root, root.val)]
        while st:
            node, path_sum = st.pop()
            # 如果该节点是叶子节点了,同时该节点的路径数值等于sum,那么就返回true
            if not node.left and not node.right and path_sum == sum:
                return True
            # 右节点,压进去一个节点的时候,将该节点的路径数值也记录下来
            if node.right:
                st.append((node.right, path_sum + node.right.val))
            # 左节点,压进去一个节点的时候,将该节点的路径数值也记录下来
            if node.left:
                st.append((node.left, path_sum + node.left.val))
        return False


113. 路径总和 II

113. 路径总和 II

自己做

思路:

求所有路径 -> 回溯法 + 需要一个path[] + result[]

代码:

# 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 __init__(self):
        self.result = []
        self.path = []
    def pathSum(self, root, targetSum):
        """
        :type root: TreeNode
        :type targetSum: int
        :rtype: List[List[int]]
        """
        if not root:
            return []

        curSum = 0
        curSum += root.val

        self.path.append(root.val)

        self.helper(root, curSum, targetSum)

        return self.result

    def helper(self, root, curSum, targetSum): # 1. 
    	# 2. 
        if not root.left and not root.right and curSum == targetSum:
            #print(self.path)
            self.result.append(list(self.path))
            return 
        if not root.left and not root.right:
            return 
		
		# 3. 
        if root.left:
            curSum += root.left.val
            self.path.append(root.left.val)
            #print(self.path)
            self.helper(root.left, curSum, targetSum)
            curSum -= root.left.val
            self.path.pop()
        if root.right:
            curSum += root.right.val
            self.path.append(root.right.val)
            self.helper(root.right, curSum, targetSum)
            curSum -= root.right.val
            self.path.pop()

迭代

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def pathSum(self, root: TreeNode, targetSum: int) -> List[List[int]]:
        if not root:
            return []
        stack = [(root, [root.val])]
        res = []
        while stack:
            node, path = stack.pop()
            if not node.left and not node.right and sum(path) == targetSum:
                res.append(path)
            if node.right:
                stack.append((node.right, path + [node.right.val]))
            if node.left:
                stack.append((node.left, path + [node.left.val]))
        return res

从中序与后序遍历序列构造二叉树

106.从中序与后序遍历序列构造二叉树

106.从中序与后序遍历序列构造二叉树

自己做

思路:

  • 中序遍历 inorder = [9,3,15,20,7] 左中右
  • 后序遍历 postorder = [9,15,7,20,3] 左右中

-> 后序遍历的最后一个结点为根结点 3

-> 根据 3 去中序遍历可以区分左右子树

-> 根据左右子树可以去后续遍历剩余元素中区分开左子树序列和右子树序列

-> 去后序遍历子树序列中寻找最后一个元素,找到子树的根结点

-> 循环反复,直到列表为空

代码:自己没做出来

python


代码随想录

思路:

如果让我们肉眼看两个序列,画一棵二叉树的话,应该分分钟都可以画出来。

在这里插入图片描述

那么代码应该怎么写呢?

说到一层一层切割,就应该想到了递归。

来看一下一共分几步:

第一步:如果数组大小为零的话,说明是空节点了。

第二步:如果不为空,那么取后序数组最后一个元素作为节点元素。

第三步:找到后序数组最后一个元素在中序数组的位置,作为切割点

第四步:切割中序数组,切成中序左数组和中序右数组 (顺序别搞反了,一定是先切中序数组)

第五步:切割后序数组,切成后序左数组和后序右数组

第六步:递归处理左区间和右区间

代码:代码是按照自己敲的

python

# 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
        """
        # 1. 
        if len(postorder) == 0:
            return None
        
        # 2.
        root = TreeNode(postorder[-1])

        # 3. 
        if len(postorder) == 1:
            return root
        
        # 4.
        delimiterIndex = 0
        for index, val in enumerate(inorder):
            if val == root.val:
                delimiterIndex = index
                break
        
        # 5. 切割中序数组,得到 中序左数组和中序右数组
        left_inorder = inorder[:delimiterIndex]
        right_inorder = inorder[delimiterIndex+1:]

        # 6. 切割后序数组,得到 后序左数组和后序右数组
        left_postorder = postorder[:len(left_inorder)]
        right_postorder = postorder[len(left_inorder):-1]

        # 7. 
        root.left = self.buildTree(left_inorder, left_postorder)
        root.right = self.buildTree(right_inorder, right_postorder)

        return root

105.从前序与中序遍历序列构造二叉树

105.从前序与中序遍历序列构造二叉树

自己做

思路:

-> 前序遍历列表第一个元素为根结点

-> 接下来的思路与上题一致

代码:

python

# 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, preorder, inorder):
        """
        :type preorder: List[int]
        :type inorder: List[int]
        :rtype: TreeNode
        """
        if len(preorder) == 0:
            return None

        root = TreeNode(preorder[0])

        if len(preorder) == 1:
            return root

        delimiterIndex = 0
        for index, val in enumerate(inorder):
            if val == root.val:
                delimiterIndex = index
                break

        left_inorder = inorder[ : delimiterIndex]
        right_inorder = inorder[delimiterIndex+1: ]

        left_preorder = preorder[1:len(left_inorder)+1]
        right_preorder = preorder[len(left_inorder)+1: ]
        
        root.left = self.buildTree(left_preorder, left_inorder)
        root.right = self.buildTree(right_preorder, right_inorder)

        return root

注意

前序和中序可以唯一确定一棵二叉树。

后序和中序可以唯一确定一棵二叉树。

那么前序和后序可不可以唯一确定一棵二叉树呢?

前序和后序不能唯一确定一棵二叉树!

反例:

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值