代码随想录算法训练营第17天 | 110.平衡二叉树 257. 二叉树的所有路径 404.左叶子之和

代码随想录刷题系列文章目录

二叉树篇


110.平衡二叉树

dfs错误思路

首先,紧跟昨日的二叉树的最大深度,最小深度这些题的思路

这道题上来我就明白了要用后序的遍历方式,但是我的错路是直接找root 的左右子树,找他们各自的最大高度,如果最大高度的绝对值在1之内,返回true

def isBalanced(self, root: Optional[TreeNode]) -> bool:
        if not root: return True
        def getheight(node):
            if not node: return 0
            left = getheight(node.left)
            right = getheight(node.right)
            return 1 + max(left, right)
        left = getheight(root.left)
        right = getheight(root.right)
        if abs(left-right) <= 1:
            return True
        return False

但是这种思路,有一个弊端
就是这种情况
在这里插入图片描述
很明显这种是不对的,因为子树就不是平衡的

dfs正确的 能过所有例子的写法

所以,如果递归过程中子树就不是平衡二叉树,最后结果也就不是平衡二叉树
所以要在geiheight的同时,子树不达标的就return 一个-1,不能继续进入递归

def getheight(self, node):
        if not node: return 0
        lefthei = self.getheight(node.left)
        if lefthei == -1: return -1
        righthei = self.getheight(node.right)
        if righthei == -1: return -1
        res = 0
        if abs(lefthei-righthei) > 1: res = -1
        else: res = 1 + max(lefthei, righthei)
        return res
    def isBalanced(self, root: Optional[TreeNode]) -> bool:
        if self.getheight(root) != -1: return True
        else: return False

这种写法,就是在找高度的同时,如果发现子树不平衡,就返回一个-1了

bfs写法

class Solution:
    def isBalanced(self, root: Optional[TreeNode]) -> bool:
        if not root:
            return True

        height_map = {}
        stack = [root]
        while stack:
            node = stack.pop()
            if node:
                stack.append(node)
                stack.append(None)
                if node.left: stack.append(node.left)
                if node.right: stack.append(node.right)
            else:
                real_node = stack.pop()
                left, right = height_map.get(real_node.left, 0), height_map.get(real_node.right, 0)
                if abs(left - right) > 1:
                    return False
                height_map[real_node] = 1 + max(left, right)
        return True

257. 二叉树的所有路径 (dfs 回溯)

这道题目要求从根节点到叶子的路径,所以需要前序遍历,这样才方便让父节点指向孩子节点,找到对应的路径。
前序的dfs写法:

  1. 确定递归参数
    要传入根节点,记录每一条路径的path,和存放结果集的result
  2. 确定递归终止条件
    本题要找到叶子节点,就开始结束的处理逻辑了(把路径放进result里)那么什么时候算是找到了叶子节点? 是当 cur不为空,其左右孩子都为空的时候,就找到叶子节点。
  3. 确定单层递归逻辑
    这里的根左右这个逻辑中,由于我们找到叶子结点之后,就把整个路径加进结果里;所以说,我们操作根这个步骤,要放在出口之前,不然的话 叶子结点加不进path

回溯的代码以后就按着这种模板写吧

# 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 binaryTreePaths(self, root: TreeNode) -> List[str]:
        path = ''
        result = []
        if not root: return result
        self.traversal(root, path, result)
        return result
    
    def traversal(self, cur: TreeNode, path: str, result: List[str]) -> None:
        path += str(cur.val)  # 根 为什么写在这里,因为最后一个节点也要加入到path中
        # 若当前节点为leave,直接输出
        if not cur.left and not cur.right:
            result.append(path)

        if cur.left:
            # + '->' 是隐藏回溯
            self.traversal(cur.left, path + '->', result)
        
        if cur.right:
            self.traversal(cur.right, path + '->', result)

然后,回溯这个过程为什么能省略,原因一定要看引用

404.左叶子之和

dfs写法 后序遍历

递归的参数没有什么可说的
首先是递归的出口,要注意是判断左叶子,不是二叉树左侧节点,所以不要上来想着层序遍历。左叶子结点的判断:结点的左子树不空,且左子结点没有孩子
其次就是每层的递归逻辑,可以说这道题的递归写法的逻辑是后序遍历的,左右子树的左叶子结点,分别统计完,用一个值加起来

def sumOfLeftLeaves(self, root: Optional[TreeNode]) -> int:
        if not root:
            return 0
        leftsum = self.sumOfLeftLeaves(root.left)
        if root.left != None and root.left.left == None and root.left.right == None:
            leftsum = root.left.val
        rightsum = self.sumOfLeftLeaves(root.right)
        sum_ = leftsum + rightsum
        return sum_

迭代写法

class Solution:
    def sumOfLeftLeaves(self, root: TreeNode) -> int:
        """
        Idea: Each time check current node's left node. 
              If current node don't have one, skip it. 
        """
        stack = []
        if root: 
            stack.append(root)
        res = 0
        
        while stack: 
            # 每次都把当前节点的左节点加进去. 
            cur_node = stack.pop()
            if cur_node.left and not cur_node.left.left and not cur_node.left.right: 
                res += cur_node.left.val
                
            if cur_node.left: 
                stack.append(cur_node.left)
            if cur_node.right: 
                stack.append(cur_node.right)
                
        return res
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值