1315 祖父节点值为偶数的节点和(dfs-自下往上处理、bfs)

1. 问题描述:

给你一棵二叉树,请你返回满足以下条件的所有节点的值之和:该节点的祖父节点的值为偶数。(一个节点的祖父节点是指该节点的父节点的父节点。)如果不存在祖父节点值为偶数的节点,那么返回 0 。

示例:

输入:root = [6,7,8,2,7,1,3,9,null,1,4,null,null,null,5]
输出:18
解释:图中红色节点的祖父节点的值为偶数,蓝色节点为这些红色节点的祖父节点。

提示:

  • 树中节点的数目在 1 到 10^4 之间。
  • 每个节点的值在 1 到 100 之间。

2. 思路分析:

① 因为是关于二叉树的题目所以可以使用递归遍历来解决(树本身就是递归定义的所以可以使用递归的方法解决),除了使用递归解决的方法之外,对于二叉树遍历还有广度优先遍历(bfs)的方法,在大多数的情况对于二叉树的题目我基本上使用的是递归遍历(dfs)的方法去解决的,下面使用的也是dfs的方法。对于二叉树遍历节点的处理方法存在两种,第一种是自上往下对节点进行处理,第二种是自下往上对接点进行处理,对于第一种自上往下进行处理的方法:是在递归方法的一开始对节点进行处理,这样我们每调用一次dfs方法,在二叉树越上面的节点在方法的一开始都会先访问到,所以它对于二叉树节点是自上往下进行处理的,对于第二种自下往上进行处理方法:一般是利用递归层层返回的特点来处理对应的情况:根据当前根节点往下递归调用之后返回的结果决定更新某些变量或者是结果集,这样就可以根据当前节点下面的子节点的情况来进行处理。对于这道题目来说比较好的方法是自下往上进行处理,因为可以利用递归层层返回节点的时候来判断当前根节点下面的子节点的情况

② 由①可以知道我们可以在递归方法调用返回到当前的根节点的时候对结果集进行处理,先判断当前的左子树是否存在(假如左子树不存在那么根本就不需要判断它的左右节点了因为它下面的节点就更不存在了),然后判断左子树的左右节点子树是否存在,假如存在那么将左右节点的值累加到声明的全局变量中,然后判断右子树是否存在假如存在那么判断右子树的左右节点是否存在,如果存在将左右节点值累加到全局变量中,而且在递归层层返回的时候只会返回当前的节点一次所以对于当前返回的节点下面的左右节点也是处理一次的,所以最终计算的答案是正确的

力扣官方提供的题解中的方法也是ok的,它的处理思路是在递归的方法中传递当前节点的父节点与祖父节点进行递归的,传递了父节点与祖父节点那么就像我在①中说到的可以自上往下处理节点了,根据当前祖父节点的值是否是偶数来累加对应的左右子树的子节点的值,并且在后面可以优化为:在递归方法中传递当前节点的父节点与祖先节点的值来进行处理

③ 除了使用dfs方法之外,还可以使用bfs广度优先遍历的方法对节点进行处理,思路也很容易理解:我们可以判断当前队列中弹出的节点是否是偶数假如是偶数那么判断它的左右子树的左右节点是否存在,如果存在那么将左右节点的值累加到结果集中

3. 代码如下:

class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None


class Solution:
    res = 0

    def dfs(self, root: TreeNode):
        if not root: return 0
        if not root.left and not root.right: return
        self.dfs(root.left)
        self.dfs(root.right)
        # 判断出当前的节点是否是偶数节点假如是偶数节点那么判断左子树是否存在假如存在那么判断它的左右节点是否存在
        if root.val % 2 == 0 and root.left:
            if root.left.left: self.res += root.left.left.val
            if root.left.right: self.res += root.left.right.val
        # 判断出当前的节点是否是偶数节点假如是偶数节点那么判断右子树是否存在假如存在那么判断它的左右节点是否存在
        if root.val % 2 == 0 and root.right:
            if root.right.left: self.res += root.right.left.val
            if root.right.right: self.res += root.right.right.val

    def sumEvenGrandparent(self, root: TreeNode) -> int:
        self.dfs(root)
        return self.res

力扣官方的递归思路:因为使用了嵌套的方法所以在第一个方法的一开始声明的变量在第二个方法中需要修改的时候需要使用nonlocal关键字来声明这样才可以修改

class Solution:
    def sumEvenGrandparent(self, root: TreeNode) -> int:
        ans = 0

        def dfs(gp_val, p_val, node):
            if not node:
                return
            if gp_val % 2 == 0:
                nonlocal ans
                ans += node.val
            dfs(p_val, node.val, node.left)
            dfs(p_val, node.val, node.right)
        dfs(1, 1, root)
        return ans

力扣官方的bfs代码:可以学习一下使用collections.deque方法

class Solution:
    def sumEvenGrandparent(self, root: TreeNode) -> int:
        q = collections.deque([root])
        ans = 0
        while len(q) > 0:
            node = q.popleft()
            if node.val % 2 == 0:
                if node.left:
                    if node.left.left:
                        ans += node.left.left.val
                    if node.left.right:
                        ans += node.left.right.val
                if node.right:
                    if node.right.left:
                        ans += node.right.left.val
                    if node.right.right:
                        ans += node.right.right.val
            if node.left:
                q.append(node.left)
            if node.right:
                q.append(node.right)
        return ans

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值