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

110. 平衡二叉树

class Solution:
    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
        return self.isBalanced(root.left) and self.isBalanced(root.right)
    def getDepth(self,root):
        if not root:
            return 0
        return 1 + max(self.getDepth(root.left), self.getDepth(root.right))

自己的思路倒是AC了,但是效率有点低。

参考了代码随想录的思路优化代码,可以定义一个getHeight函数用于计算深度,并在计算的过程中给非平衡的二叉树打上标记。换句话说,在求子树高度的时候可以先判断下是否是平衡二叉树,用来剪枝并退出本次递归,效率地解决了问题。

class Solution:
    def isBalanced(self, root: Optional[TreeNode]) -> bool:
        if not root: return True
        return self.getHeight(root) != -1
    
    def getHeight(self,root):
        if not root:
            return 0
        leftHeight = self.getHeight(root.left)
        if leftHeight == -1: return -1
        rightHeight = self.getHeight(root.right)
        if rightHeight == -1: return -1
        if abs(leftHeight - rightHeight) > 1: return -1
        return max(leftHeight, rightHeight) + 1

257. 二叉树的所有路径

 

利用递归回溯,记录下所有的路径。

结果是前序遍历的顺序因此使用前序遍历。终止条件就是遇到叶子节点,就把路径加进结果集。递归过程就是前序遍历的递归过程,使用path字符串和result数组记录过程。对于每个栈帧都有一个path,这一层如果不是叶子节点,下一层就给path加上'->'符号递归,直到遇到叶子节点记录后回溯上一栈帧,这时栈帧的path是原本记录好的,继续递归过程。如此循环即可得到所有路径。

class Solution:
    def binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:
        result = []
        self.getPath(root,'',result)
        return result
    
    def getPath(self, node, path, result):
        if node:
            path += str(node.val)
            if not node.left and not node.right:
                result.append(path)
            else:
                path += '->'
                if node.left: self.getPath(node.left,path,result)
                if node.right: self.getPath(node.right,path,result)

404. 左叶子之和

利用回溯记录左叶子集,如果是从右边回来的,判断一下右边是不是叶子,如果是,剔除结果。

class Solution:
    def sumOfLeftLeaves(self, root: Optional[TreeNode]) -> int:
        if not root.left and not root.right:
            return 0
        res = []
        self.checkSum(root, res)
        return sum(res)
    def checkSum(self, root, cnt):
        if not root.left and not root.right:
            cnt.append(root.val)
        if root.left: 
            self.checkSum(root.left,cnt)
        if root.right: 
            self.checkSum(root.right,cnt)
            if not root.right.right and not root.right.left:
                cnt.pop()

相对来说,代码随想录的方法更加优雅。遇到叶子节点终止,返回0;回溯后如果发现是左叶子,那就把结果加上。

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

今日总结:

回溯发生在递归返回,如果每次都记录递归操作,返回时再操作就是操作回溯。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值