回溯法在二叉树中的应用(或位运算和递归结合)

1022. 从根到叶的二进制数之和

难度简单219收藏分享切换为英文接收动态反馈

给出一棵二叉树,其上每个结点的值都是 0 或 1 。每一条从根到叶的路径都代表一个从最高有效位开始的二进制数。

  • 例如,如果路径为 0 -> 1 -> 1 -> 0 -> 1,那么它表示二进制数 01101,也就是 13 。

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

返回这些数字之和。题目数据保证答案是一个 32 位 整数。

示例 1:

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

示例 2:

输入:root = [0]
输出:0

提示:

  • 树中的节点数在 [1, 1000] 范围内
  • Node.val 仅为 0 或 1 

        大体意思都能懂,只是在二叉树的递归回溯法中与普通的递归回溯法还是有区别的,其实只要理解了递归回溯的思想,这些算不上区别,在思路上,因为传统的回溯法一般都会和标记数组一起使用,来达到深度优先搜索完成后的向来的方向回退一步再进行选择的目的,但是二叉树不同,因为普通的二叉树,一旦进入就很难回头了,所以要保证分叉进入不同的路之后,当一条路走到尽头时,要有办法在回到第一个分叉的地方,所以,左右子树的递归要和回溯结合在一起,也就是左右子树递归多少次,就要回溯多少次,可能会有人不理解回溯那么多次不会把两个相同父节点的叶子结点给忽略了吗?这其实就要从进入和离开子树的递归说起了,我们看到的递归仅仅有一两句话,但是实际上他是由很多个递归嵌套起来的,举个例子

dfs(左子树)

{

  dfs(左子树的左子树){。。。。。。回溯。。。return ;}

dfs(左子树的右子树){。。。。。。回溯。。。return ;}

回溯。。。

      return ;

}

dfs(右子树)

{

   。。。。。

}

所以说在第一个叶子结点执行完后,接着是回溯递归该叶子结点父节点的右子树,然后再通过两次回溯到达叶子结点的上一层,再进行递归,所以说也就有了二叉树全部的不同路径的走法

那接下来就是代码了(可能有点眼花,建议复制到编译器里看)

class Solution {

public:

    vector<int >p;

    vector<vector<int>> ans;

    void dfs(TreeNode* root,vector<vector<int> >&ans,vector<int> &p)

    {

        if(!root->left&&!root->right)

        {

            p.push_back(root->val);

            ans.push_back(p);

            return ;

        }

        else

        {

            p.push_back(root->val);

            if(root->left)

            {dfs(root->left,ans,p);p.pop_back();}

            if(root->right)

            {dfs(root->right,ans,p);p.pop_back();}

            

        }

    }

    int sumRootToLeaf(TreeNode* root) {

        int result=0;

        dfs(root,ans,p);

        for(auto &i:ans)

        {

            int sum=0;

            int k=i.size()-1;

            for(auto &j:i)

            {

                sum+=pow(2,k--)*j;

            }

            result+=sum;

        }

        return result;

    }

};

2.其实这个题还有更简单的方法,就是省去二进制求和的代码,用位运算加以取代,再以递归取代回溯法,也就是官方的方法,让我学到了位运算的用处,他可以直接将二进制进行运算,从而节省了计算机计算的时间,大大提高了代码效率,建议能用位运算,别用运算法,

 这里以叶子节点为递归结束的条件,每当碰到一个叶子节点,就返回当前的结果,在最后的大左右子树进行总求和进行计算,真的很牛啊,学到老活到老。

     

                                                                    算法之路————递归与回溯应用只二叉树

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二叉树是一种重要的数据结构,它的遍历方式有递归和非递归两种。下面将分别介绍二叉树的基本运算和非递归遍历算法。 1. 二叉树的基本运算 建立二叉树的三叉链式存储结构,可以通过以下步骤完成二叉树的基本运算: - 从键盘上输入二叉树的各个结点,建立三叉链表 - 输出该二叉树 - 递归的先序遍历、序遍历、后序遍历算法 - 非递归的先序遍历、序遍历、后序遍历算法 - 非递归的层次遍历算法 2. 非递归遍历算法 非递归遍历算法主要引入了堆栈和队列的思想,下面分别介绍非递归的先序遍历、序遍历、后序遍历和层次遍历算法。 - 非递归的先序遍历算法: ```python def preorderTraversal(root): if not root: return [] stack, res = [root], [] while stack: node = stack.pop() res.append(node.val) if node.right: stack.append(node.right) if node.left: stack.append(node.left) return res ``` - 非递归序遍历算法: ```python def inorderTraversal(root): if not root: return [] stack, res = [], [] while stack or root: if root: stack.append(root) root = root.left else: node = stack.pop() res.append(node.val) root = node.right return res ``` - 非递归的后序遍历算法: ```python def postorderTraversal(root): if not root: return [] stack, res = [root], [] while stack: node = stack.pop() res.append(node.val) if node.left: stack.append(node.left) if node.right: stack.append(node.right) return res[::-1] ``` - 非递归的层次遍历算法: ```python def levelOrder(root): if not root: return [] queue, res = [root], [] while queue: level = [] for i in range(len(queue)): node = queue.pop(0) level.append(node.val) if node.left: queue.append(node.left) if node.right: queue.append(node.right) res.append(level) return res ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值