【数据结构_12】二叉树(4)

一、二叉树的层序遍历

思路:可以按照先序的方式来遍历这个树,递归的时候,给递归方法,加上辅助的参数,level表示当前层数,递归过程中,根据level的值,决定当前整个节点要放到哪个list中。这个题目中,是通过二维list表示结果的,list中的[0]的元素就是根节点,如果把根节点视为第 0 层,此时的level就是和下标对应上了,如果把根节点视为第一层,就需要把level-1再作为下标。

代码段:

java 复制代码
    public void levelOrderHelper(TreeNode root, int k,List<List<Integer>> result){
        if(root == null){
            return ;
        }
        //当前level这一层的List是否被创建出来了
        if(result.size() == k){
            result.add(new ArrayList<>());
        }
        //取出当前元素,添加到第level行中
        List<Integer> curRow = result.get(k);
        curRow.add(root.val);
        //递归处理左右子树
        levelOrderHelper(root.left,k+1,result);
        levelOrderHelper(root.right,k+1,result);
    }



    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> result = new ArrayList<>();
        if(root == null){
            return result ;
        }

        levelOrderHelper(root,0,result);
        return  result;

    }

二、二叉树的最近公共祖先

从根节点到达这个指定节点,路径上经过的所有节点,都可以视为这个节点的祖先。所谓的公共祖先,意味着公共祖先子树中级同时包含了这两个节点。比如,确认了公共祖先这个节点,确实包含了p和q这两个节点,也就意味着p和q就可能出现在三个位置:

1.p/q是根节点

2.p/q存在于左子树

3.p/q存在于右子树

如果是最近的公共祖先,意味着p和q就会分布在上述三种情况的两种之中

其他的公共祖先,意味着p和q都是分布在上述三种情况的一种之中

代码的整体思路:

从根节点出发,递归地针对每个子树进行茶渣p和q的操作,对于任意一个节点,在根节点中查找p和q,在左子树中查找p和q,在右子树中查找p和q。针对上述三个范围的查找,分别使用int变量来表示查找结果.如果找到p或者q认为返回值为1;如果没找到p或者q返回值为0.

再将上述三个结果进行相加,如果

结果为0,意味着当前节点不是p和q的祖先

如果结果为1,意味着当前节点可能是p或者q的祖先

如果结果为2,意味着当前节点一定是p和q的最近公共祖先。

代码段如下:

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    private TreeNode lca = null;
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        lca = null;
        if(root == null){
            return  null;
        }
        if(root == p || root == q){
            return root;
        }
        //需要使用一个辅助方法进行递归,完成上述的逻辑
        find(root,p,q);
        return  lca;
    }


    public  int find(TreeNode root,TreeNode p,TreeNode q){
        if(root == null){
            return 0;
        }
        //针对根节点查找返回的0/1
        int mid = (root == p || root ==q )?1:0;
        //针对左子树查找返回的0/1
        int left = find(root.left,p,q);
        //针对右子树查找返回的 0 / 1
        int right = find(root.right,p,q);
        if(mid + right + left ==2){
            //说明root就是最近的公共祖先
            //最近公共祖先只有一个,但是find方法是递归过程中找到的
            //如何把这个公共祖先返回到上一个方法中去呢?
            lca = root;
        }
        return mid + right + left > 0 ? 1:0;
    }
}

这道题的一些难点:

1.理解公共祖先和最近公共祖先

2.分析出公共祖先和最近公共祖先的差异(代码来描述);三个范围中,其中的两个范围分别找到了p和q,就是最近公共祖先

3.编写代码,通过三个 0 / 1 这样的int值相加,看是否为2

4.如何方便简单地拿到返回值

三、根据前序遍历和中序遍历序列构造二叉树

关键结论:

1.先序的第一个元素,就是根节点

2.先序中,根节点左侧的就是左子树的中序;根节点右侧的就是右子树的中西

3.先序中,知道了哪些节点是左子树,哪些节点是右子树之后,此时,先序中对应的序列,也就是左右子树的先序结果

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    //首先创建一个index来表示当前去到了preorder中的哪个元素
    private int index = 0;
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        index =0;
        //创建一个方法来辅助创建树
        return buildTreeHelper(preorder,inorder,0, inorder.length);
    }

    public TreeNode buildTreeHelper(int[] preorder,int[] inorder, int inleft ,int inright){
        if(inleft >= inright){
           //给定的区间是空区间,意味着对应空树
            return  null;
        }
        if(index >= preorder.length){
            //说明已经遍历完了preorder这个数组
            return  null;
        }
        //取出index对应的元素,构造出当前的节点
        TreeNode root  = new TreeNode(preorder[index]);
        index++;
        //接下来要找到root在中序序列的位置
        int pos = findPos(inorder,inleft,inright,root.val);
        //再递归左子树,递归右子树
        root.left =buildTreeHelper(preorder,inorder,inleft,pos);
        root.right =buildTreeHelper(preorder,inorder,pos+1,inright);
        return root;
    }

    public int findPos(int[] inorder,int inleft,int inright,int val){
        //循环遍历
        for(int i=inleft;i<inright;i++){
            if(inorder[i]== val){
                return  i;
            }
        }
        return -1;

    }
}

四、从中序与后序遍历序列构造二叉树

相关推荐
茶不思l2 小时前
数据结构-链表
数据结构·链表
Brookty2 小时前
【算法】快速排序、归并排序(非递归版)
数据结构·算法·排序算法
李帅朋3 小时前
选择排序(简单选择排序、堆排序)
数据结构·算法·排序算法
半桔4 小时前
C++11特性补充
开发语言·数据结构·c++·算法·c++11
可乐^奶茶5 小时前
2026《数据结构》考研复习笔记四(第一章)
数据结构·笔记·考研
三原5 小时前
实现多选树形组件,我把递归用明白了
前端·数据结构·vue.js
葵花日记5 小时前
数据结构——栈
数据结构
FAREWELL000755 小时前
C#进阶学习(八)常见的泛型数据结构类(3)SortedDictionary<TKey, TValue>与SortedList<TKey, TValue>
数据结构·学习·c#·sorteddictioary·sortedlist
一只鱼^_6 小时前
第 28 场 蓝桥月赛
开发语言·数据结构·c++·算法·面试·蓝桥杯
三体世界7 小时前
Linux 动、静态库的实现
linux·开发语言·数据结构·c++·windows·算法