代码随想录day17 平衡二叉树 所有路径 左叶子之和

110. 平衡二叉树 - 力扣(LeetCode)

getDepth()和isBalanced()都在递归,getDepth()就是前面做过的求树最大深度;isBalanced()的逻辑是:判断平衡树应该要比较当前节点的左右子树最大深度,若相差不超过1,再接着判断左孩子的两个子树、右孩子的两个子树,退出递归的条件是节点为空。只有在当前节点、左孩子、右孩子都满足条件时是平衡二叉树。

class Solution:
    def getDepth(self, root):
        if not root:
            return 0
        
        return 1 + max(self.getDepth(root.left), self.getDepth(root.right))

    def isBalanced(self, root: Optional[TreeNode]) -> bool:
        if not root:
            return True
        
        if abs(self.getDepth(root.left) - self.getDepth(root.right)) > 1:
            return False
        else:
            return self.isBalanced(root.left) and self.isBalanced(root.right)

 P.S. 讨论一下树的高度与深度:在上题getDepth()和之前的求二叉树最大深度题目中, 由于根节点的高度==二叉树的深度,我们求的是根节点高度。如果题目要求找到值==val的节点的深度,就需要用求深度的逻辑写代码。下面用求深度的逻辑写getDepth():

class Solution:
    def getDepth(self, node, depth, res):
        if not node:
            res[0] = max(res[0], depth-1)
            return
        
        self.getDepth(node.left, depth+1, res)
        self.getDepth(node.right, depth+1, res)

    def maxDepth(self, root: Optional[TreeNode]) -> int:
        if not root:
            return 0

        res = [0]
        self.getDepth(root, 1, res)
        return res[0]

* res是用list封装int,传入函数;

* 递归调用getDepth()时传入depth+1,其实是在做回溯;

* 易错:当节点为空,记得比较res和depth-1而非depth,因为空节点不算数。 

257. 二叉树的所有路径 - 力扣(LeetCode)

1)递归+回溯

易错1:path.append(str(node.val)),否则paths.append("->".join(path))时执行出错;

易错2:不可以直接paths.append(path),否则在后面path.pop()会连带影响paths;

易错3:回溯,即path.pop()的位置、次数。

class Solution:
    def getPath(self, node, path, paths):
        path.append(str(node.val))

        if not (node.left or node.right): #is leaf
            paths.append("->".join(path))
            path.pop()
            return 
    
        elif not node.left:
            self.getPath(node.right, path, paths)
            path.pop()
        elif not node.right:
            self.getPath(node.left, path, paths)
            path.pop()

        else:
            self.getPath(node.left, path, paths)
            self.getPath(node.right, path, paths)
            path.pop()

        
    def binaryTreePaths(self, root):
        if not root:
            return []

        path = []
        paths = []
        self.getPath(root, path, paths)
            
        return paths

调整与一下path.pop()的位置,使得每次递归(调用self.getPath)时紧跟一个回溯path.pop():

class Solution:
    def getPath(self, node, path, paths):
        path.append(str(node.val))

        if not (node.left or node.right): #is leaf
            paths.append("->".join(path))
            return 
    
        elif not node.left:
            self.getPath(node.right, path, paths)
            path.pop()
        elif not node.right:
            self.getPath(node.left, path, paths)
            path.pop()

        else:
            self.getPath(node.left, path, paths)
            path.pop()
            self.getPath(node.right, path, paths)
            path.pop()

        
    def binaryTreePaths(self, root):
        if not root:
            return []

        path = []
        paths = []
        self.getPath(root, path, paths)
            
        return paths

再简化一下条件判断:(记得避免将空节点传入self.getPath)

class Solution:
    def getPath(self, node, path, paths):
        path.append(str(node.val))

        if not (node.left or node.right): #is leaf
            paths.append("->".join(path))
            return 
    
        if node.left:
            self.getPath(node.left, path, paths)
            path.pop()

        if node.right:
            self.getPath(node.right, path, paths)
            path.pop()

        
    def binaryTreePaths(self, root):
        if not root:
            return []

        path = []
        paths = []
        self.getPath(root, path, paths)
            
        return paths

* 补充:Python的参数传递机制

x = 10  # 全局变量

def modify_immutable():
    global x  # 使用global关键字声明
    print("Before modification:", x)
    x = 20
    print("After modification:", x)

print("Original x:", x)  # 输出: Original x: 10
modify_immutable()       # 修改全局变量x的值
print("Modified x:", x)  # 输出: Modified x: 20
my_list = [1, 2, 3]  # 全局变量

def modify_mutable():
    print("Before modification:", my_list)
    my_list.append(4)  # 直接修改全局列表
    print("After modification:", my_list)

print("Original my_list:", my_list)  # 输出: Original my_list: [1, 2, 3]
modify_mutable()                     # 修改全局列表
print("Modified my_list:", my_list)  # 输出: Modified my_list: [1, 2, 3, 4]

 

2)迭代,用两个栈存放节点和其对应的路径。每次弹出栈中的节点和从root到该节点的路径(字符串),若为叶子节点,对应路径推入结果列表,若不是叶子,再将非空孩子节点与对应的路径推入两个栈。

class Solution:
    def binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:
        if not root: 
            return []

        paths = [str(root.val)]
        nodes = [root]
        res = []
        while nodes:
            node = nodes.pop()
            path = paths.pop()

            if not node.left and not node.right:
                res.append(path)
            
            else:
                if node.left:
                    nodes.append(node.left)
                    paths.append(path + "->" + str(node.left.val))
                if node.right:
                    nodes.append(node.right)
                    paths.append(path + "->" + str(node.right.val))
        
        return res

404. 左叶子之和 - 力扣(LeetCode)

* cnt:python int不可变,要用list封装。

class Solution:
    def func(self, node, cnt):
        if node.left:
            if not self.notleaf(node.left): #left node is leaf
                cnt[0] += node.left.val
            else:       #left node is not leaf
                self.func(node.left, cnt)
        
        if node.right:
            if self.notleaf(node.right): #right node is not leaf
                self.func(node.right, cnt)
        
    def notleaf(self, node):
        return node.left or node.right

    def sumOfLeftLeaves(self, root: Optional[TreeNode]) -> int:
        if not root:
            return 0
        
        cnt = [0]
        self.func(root, cnt)
        return cnt[0]

更简洁的解法: 

class Solution:
    def sumOfLeftLeaves(self, root: Optional[TreeNode]) -> int:
        if not root:
            return 0
        
        if root.left and not root.left.left and not root.left.right:
            return root.left.val + self.sumOfLeftLeaves(root.left) + self.sumOfLeftLeaves(root.right)
        
        else:
            return self.sumOfLeftLeaves(root.left) + self.sumOfLeftLeaves(root.right)

或者

class Solution:
    def sumOfLeftLeaves(self, root: Optional[TreeNode]) -> int:
        if not root:
            return 0
        
        tmp = self.sumOfLeftLeaves(root.left) + self.sumOfLeftLeaves(root.right)

        if root.left and not root.left.left and not root.left.right:
            return root.left.val + tmp
        
        else:
            return tmp

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,我们需要了解什么是扩展二叉树。扩展二叉树是一种二叉树的表示方法,其中每个非叶子节点都有两个子节点,但其中一个或两个子节点可以为空。因此,扩展二叉树的前序序列可以被表示为一个字符串,其中空节点用字符“#”表示。例如,扩展二叉树“1(2(4(#)(#))(5(#)(#)))”可以表示为前序序列“124##5##”。 现在我们来考虑如何构建二叉树。我们可以使用递归的方法来构建二叉树,每次递归都处理当前节点的子树和右子树。具体来说,我们可以先读取前序序列中的下一个字符,如果当前字符是“#”,则表示该节点为空;否则,我们可以将该字符转换为数字并创建一个新节点,然后递归构建该节点的子树和右子树。 下面是 Python 代码实现: ``` python class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right def buildTree(preorder): def helper(): val = preorder.pop(0) if val == '#': return None node = TreeNode(int(val)) node.left = helper() node.right = helper() return node return helper() ``` 接下来,我们需要计算给定二叉树的所有叶子之和叶子是指没有右子树的子树节点。因此,我们可以使用递归的方法遍历整个二叉树,在遍历的过程中累加所有叶子节点的值。具体来说,对于每个节点,我们将其子节点的值加入结果中,然后递归处理其子树和右子树。 下面是 Python 代码实现: ``` python def sumOfLeftLeaves(root): def helper(node, is_left): if not node: return 0 if not node.left and not node.right and is_left: return node.val return helper(node.left, True) + helper(node.right, False) return helper(root, False) ``` 完整代码如下: ``` python class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right def buildTree(preorder): def helper(): val = preorder.pop(0) if val == '#': return None node = TreeNode(int(val)) node.left = helper() node.right = helper() return node return helper() def sumOfLeftLeaves(root): def helper(node, is_left): if not node: return 0 if not node.left and not node.right and is_left: return node.val return helper(node.left, True) + helper(node.right, False) return helper(root, False) preorder = '1(2(4(#)(#))(5(#)(#)))' root = buildTree(list(preorder)) print(sumOfLeftLeaves(root)) # 输出 4 ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值