二叉树-常见题目

本文深入探讨了二叉树的三种核心算法:寻找最近公共祖先、转换为排序双向链表及由前序和中序遍历构建二叉树。通过实例解析,详细介绍了每种算法的设计思路和实现步骤。

一、给定一个二叉树,找到该树中两个指定节点的最近公共祖先
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。
在这里插入图片描述
如上图,D和E的最近公共祖先就是B,G和F的最近公共祖先就是E,(一个节点也可以是自己的祖先)

//这个变量是最近公共节点
    private TreeNode Lac = null;

    //判断公共祖先
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null) {
            return null;
        }
        findNode(root, p, q);
        return Lac;
    }

    //如果再root中能找到p或者q,就返回true,否则返回false
    private boolean findNode(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null) {
            return false;
        }
        //查找:后序遍历形式进行查找
        int left = findNode(root.left, p, q) ? 1 : 0;
        int right = findNode(root.right, p, q) ? 1 : 0;
        //返回根节点
        int mid = (root == p || root == q) ? 1 : 0;

        if (left + right + mid == 2) {
            Lac = root;
        }

        return (left + right + mid) > 0;
    }

二、将二叉搜索树转成排序双向链表(二叉搜索树的中序遍历就是一个排好序的)

public class Solution {
        public TreeNode Convert(TreeNode root) {
        if (root == null) {
            return null;
        }
        if (root.left == null && root.right == null) {
            return root;
        }
        //先递归处理左子树,相当于把左子树已经完整的转换成双向链表,返回值为左子树链表的头节点
        TreeNode left = Convert(root.left);
        //根节点追加到左子树链表的末尾(链表尾插)
        //先找到链表的末尾(right相当于是next,left相当于prev)
        TreeNode leftTail = left;
        while (leftTail != null && leftTail.right != null) {
            leftTail = leftTail.right;
        }
        if (leftTail != null) {
            leftTail.right = root;
            root.left = leftTail;
        }


        //最后递归处理右子树(得到右子树的头节点)
        TreeNode right = Convert(root.right);
        if (right != null) {
            root.right = right;
            right.left = root;
        }
        //left不为空返回left,为空的话就返回right
        return left!=null?left:root;
    }
}

三、根据一棵树的前序遍历和中序遍历结构构建这棵二叉树

class Solution {
    private int index=0;
    public  TreeNode buildTree(int[] preorder, int[] inorder) {
        index=0;
        return buildTreeHelper(preorder,inorder,0,inorder.length);

    }

    private TreeNode buildTreeHelper(int[] preorder, int[] inorder, int inorderLeft, int inorderRight) {
        if(inorderLeft>=inorderRight){
            return null;
        }
        if(index>=inorder.length){
            return null;
        }
        TreeNode newNode=new TreeNode(preorder[index]);
        //左子树对应的中序区间  inorderLeft到pos结束,右子树对应的中序区间
        int pos=find(inorder,inorderLeft,inorderRight,newNode.val);
        index++;
        newNode.left=buildTreeHelper(preorder,inorder,inorderLeft,pos);
        newNode.right=buildTreeHelper(preorder,inorder,pos+1,inorderRight);
        return newNode;
    }

    private int find(int[] inorder, int inorderLeft, int inorderRight, int val) {
        for(int i=inorderLeft;i<inorderRight;i++){
            if(inorder[i]==val){
                return i;
            }
        }
        return -1;
    }
}
(1)非递归定义 树(tree)是由n(n≥0)个结点组成的有限集合。n=0的树称为空树;n>0的树T: ① 有且仅有一个结点n0,它没有前驱结点,只有后继结点。n0称作树的根(root)结点。 ② 除结点外n0 , 其余的每一个结点都有且仅有一个直接前驱结点;有零个或多个直接后继结点。 (2)递归定义 一颗大树分成几个大的分枝,每个大分枝再分成几个小分枝,小分枝再分成更小的分枝,… ,每个分枝也都是一颗树,由此我们可以给出树的递归定义。 树(tree)是由n(n≥0)个结点组成的有限集合。n=0的树称为空树;n>0的树T: ① 有且仅有一个结点n0,它没有前驱结点,只有后继结点。n0称作树的根(root)结点。 ② 除根结点之外的其他结点分为m(m≥0)个互不相交的集合T0,T1,…,Tm-1,其中每个集合Ti(0≤i<m)本身又是一棵树,称为根的子树(subtree)。 2、掌握树的各种术语: (1) 父母、孩子与兄弟结点 (2) 度 (3) 结点层次、树的高度 (4) 边、路径 (5) 无序树、有序树 (6) 森林 3、二叉树的定义 二叉树(binary tree)是由n(n≥0)个结点组成的有限集合,此集合或者为空,或者由一个根结点加上两棵分别称为左、右子树的,互不相交的二叉树组成。 二叉树可以为空集,因此根可以有空的左子树或者右子树,亦或者左、右子树皆为空。 4、掌握二叉树的五个性质 5、二叉树的二叉链表存储。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值