2.2基本算法之递归和自调用函数_LeetCode1022: 从根到叶的二进制数之和

题目介绍

描述:

给出一棵二叉树,其上每个结点的值都是 0 或 1 。每一条从根到叶的路径都代表一个从最高有效位开始的二进制数。例如,如果路径为 0 -> 1 -> 1 -> 0 -> 1,那么它表示二进制数 01101,也就是 13 。

对树上的每一片叶子,我们都要找出从根到该叶子的路径所表示的数字。

以 10^9 + 7 为模,返回这些数字之和。

65a9c79d211ea54d36f53adb22273dba.png
输入:[1,0,1,0,1,0,1]
输出:22
解释:(100) + (101) + (110) + (111) = 4 + 5 + 6 + 7 = 22

提示:

树中的结点数介于 1 和 1000 之间。
node.val 为 0 或 1 。

解题思路:

递归算法的关键是要明确函数的「定义」是什么,然后相信这个定义,利用这个定义推导最终结果。
写树相关的算法,简单说就是,先搞清楚当前 root 节点该做什么,然后根据函数定义递归调用子节点,递归调用会让孩子节点做相同的事情。
二叉树题目的一个难点在于如何通过题目的要求思考出每一个节点需要做什么

二叉树解题策略

一 递归 二 队列 + 迭代 (层次遍历) 三 栈 + 迭代 (非递归遍历) 四 其它

三种基本的遍历方式,都可以用递归来实现。写递归算法的时候,需要注意递归退出条件以及递归操作的表达。

参看题目,采取DFS比较适合。第一步,找出每一个根到叶的路径,第二步把这个数字转换成二进制。Python有个bin函数可以实现十进制转换为二进制。

自己的解法实现

def sumRootToLeaf(self, root):
        if not root: return 0
        self.res = 0
        def dfs(node, num):
            if not node: return
            num = (num << 1) + node.val
            if not node.left and not node.right:
                self.res += num
                return
            dfs(node.left, num)
            dfs(node.right, num)
        dfs(root, 0)
        return self.res

网上比较优秀的解法

解法一

def sumRootToLeaf2(self, root):
        def dfs(node, n):
            if not node: return 0
            n = n*2 + node.val
            if not node.left and not node.right:
                return n
            return (dfs(node.left, n) + dfs(node.right, n)) % (10**9 + 7)
        return dfs(root, 0)

解法二

DFS深度优先

def sumRootToLeaf3(self, root):
        if not root: return 0
        stack, res = [(root, root.val)], 0
        while stack:
            node, num = stack.pop()
            if not node.left and not node.right:
                res += num
            if node.right:
                stack.append((node.right, (num << 1) + node.right.val))
            if node.left:
                stack.append((node.left, (num << 1) + node.right.val))
        return res % (10**9 + 7)

解法三

BFS广度优先

def sumRootToLeaf4(self, root):
        from collections import deque
        queue = deque([(root, 0)])  # 注意这里0与上面栈区别
        res = 0

        while queue:
            for _ in range(len(queue)):
                node, val = queue.popleft()
                num = val * 2 + node.val  # 因为初始是0,并没有加上本身节点的val
                if not node.left and not node.right:
                    res += num
                if node.left:
                    queue.append((node.left, num))
                if node.right:
                    queue.append((node.right, num))
        return res % (10**9 + 7)

相关知识总结和思考

相关知识:

BFS:广度/宽度优先。其实就是从上到下,先把每一层遍历完之后再遍历一下一层。

可以使用Queue的数据结构。我们将root节点初始化进队列,通过消耗尾部,插入头部的方式来完成BFS。

二叉搜索树(BST)的特性:

  1. 若它的左子树不为空,则所有左子树上的值均小于其根节点的值
  2. 若它的右子树不为空,则所有右子树上的值均大于其根节点的值
  3. 它的左右子树也分别为二叉搜索树

递归与迭代的区别

递归:重复调用函数自身实现循环称为递归; 迭代:利用变量的原值推出新值称为迭代,或者说迭代是函数内某段代码实现循环;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值