哪两种遍历方式可以唯一确定一棵二叉树,结合力扣105题

仅使用先序遍历和中序遍历或后序遍历和中序遍历的组合可以唯一确定一棵二叉树。先序遍历提供根节点,中序遍历根据根节点分割左子树和右子树,通过递归构建整棵树。文章结合LeetCode 105题,解释了如何利用这两种遍历方式构建二叉树。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对于一棵树的前中序三种顺序的遍历方式,任何一种单独拿出来都无法确定一棵树,那么两种遍历方式得到的节点数据能否构建一棵二叉树呢?
先来看看能有哪几种组合:

  1. 先序遍历 + 中序遍历
  2. 后序遍历 + 中序遍历
  3. 先序遍历 + 后续遍历(不可行)

以上三种组合都可以组成二叉树,但是只有前两种组合可以唯一确定一棵二叉树,最后一种也就是先序遍历 + 后序遍历无法唯一确定一棵二叉树。为什么呢?
下给出一棵树的前中后序遍历:
先序遍历:A B D H L E C F I J M N G K
中序遍历:D H L B E A I F N M J C G K
后序遍历:L H D E B I N M J F K G C A
我们要从以上数据中的到什么样的信息才能组成一棵二叉树?
答案是节点的顺序。
我们怎么能知道顺序呢?
先序和后序可以告诉我们根节点,只不过先序遍历的根节点从前往后,后序遍历的根节点从后往前,也正是因为先序遍历和后序遍历都只能告诉我们根节点这个信息,所以他们两个在一起是没办法得到足够信息去构建二叉树的。我们知道根节点之后,可以拿这个根节点在中序遍历的数据中,以该节点为中心,节点左面为该节点的左子树,节点右面为该节点的右子树。很明显上述的规律有递归的特性。
从上面的叙述中可以得知,先序遍历和后序遍历对于我们组建一个二叉树所能提供的信息都只是根节点,我们依次拿着根节点去中序遍历分割左子树和右子树,在通过递归组成整颗树。
拿例子中的树来验证上述:

  1. 先从先序遍历中拿出根节点A,去中序遍历分割左右子树。

在这里插入图片描述
2. 拿出先序遍历的下个节点B,去1中分割好的A的左子树中去分割
在这里插入图片描述
3. 拿着先序遍历的下个节点D,去2中分割好的左子树中去分割
在这里插入图片描述
4. 拿着先序遍历的下个节点H去3中分割好的左子树,不对3中根节点没有左子树,根据遍历的特点H为D的右子树中的节点,
在这里插入图片描述
至此A的左子树全部分割结束,可以根据上面几点画出A的左子树。
在这里插入图片描述
再用同样的方法在先序遍历中取根节点,在中序遍历分割好的A的右子树中去依次分割,最终可以画出整颗树如下图:
在这里插入图片描述

LeetCode105: 从前序与中序遍历序列构造二叉树
下面通过代码来运用上述观点:

package leetcode.p105;

import leetcode.TreeNode;

import java.util.Arrays;

public class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
    	//递归出口
        if (preorder.length == 0) {
            return null;
        }

        int rootValue = preorder[0];
        TreeNode root = new TreeNode(rootValue);
        // 左子树的结点个数?
        int leftSize = 0;
        for (int i = 0; i < inorder.length; i++) {
            if (inorder[i] == rootValue) {
                leftSize = i;
            }
        }
        int rightSize = inorder.length - leftSize - 1;

        // 左子树的前序和中序
        int[] leftPreorder = Arrays.copyOfRange(preorder, 1, 1 + leftSize);
        int[] leftInorder = Arrays.copyOfRange(inorder, 0, leftSize);
        root.left = buildTree(leftPreorder, leftInorder);

        // 右子树的前序和中序
        int[] rightPreorder = Arrays.copyOfRange(preorder, 1 + leftSize, preorder.length);
        int[] rightInorder = Arrays.copyOfRange(inorder, leftSize + 1, inorder.length);
        root.right = buildTree(rightPreorder, rightInorder);

        return root;
    }
}

虽然上面代码不是最优解,但是在我看来是最方便理解
前序遍历 + 中序遍历可以构建一棵二叉树的代码。
后序遍历 + 中序遍历同理,只不过后序遍历根节点从后往前。

好的,我们先了解一下力(LeetCode)上关于“完全二叉树”的目以及如何用 C 语言解决这类问。 ### 完全二叉树的概念 完全二叉树是一种特殊的二叉树结构,在这种类型的二叉树中: - 所有层次除了最后一层节点都必须填满。 - 最后一层的节点尽可能靠左排列。 #### 特点: 1. **高度**:对于含有 n 个结点的完全二叉树来说,它的最小层数为 `log₂n + 1` (向上取整); 2. **叶子分布**:所有叶结点只能出现在最下面两层,并且从左到右依次排布; ### 力上的例子 - 判断是否为完全二叉树 在 LeetCode 上有一道叫做 [958. 二叉树的完全性检验](https://leetcode.cn/problems/check-completeness-of-a-binary-tree/)。这是一道检查给定的二叉树是不是完全二叉树的问。下面是这个问的一个简单版本及其解决方案: ```c #include <stdio.h> #include <stdbool.h> // 定义节点 typedef struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; } TreeNode; bool isCompleteTree(TreeNode* root){ if (!root) return true; // 空也是完整的 /* 这里可以采用广度优先搜索(BFS),通过队列实现 */ } ``` 为了完整地解答此问并保证程序能够准确运行,您需要了解更多的细节如构建一个合适的 BFS 或者其他算法来遍历、处理边界条件等。这里只给出了框架性的代码片段作为示例。 如果想要进一步学习和实践有关于完全二叉树的知识与解法,建议深入研究相关的数据结构理论知识,并尝试完成更多类似目以提高编码能力。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南山不太冷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值