二叉树算法题总结

1.合并二叉树(考过)

已知两颗二叉树,将它们合并成一颗二叉树。合并规则是:都存在的结点,就将结点值加起来,否则空的位置就由另一个树的结点来代替。例如:
两颗二叉树是:
                                                                    Tree 1



                                                                        Tree 2
 


                                                                    合并后的树为

数据范围:树上节点数量满足 0≤n≤500,树上节点的值一定在32位整型范围内。

进阶:空间复杂度O(1) ,时间复杂度O(n)

思路解析:

        1.先判断符合哪种遍历方式,可以看出来按照根左右进行遍历,也就是前序遍历。

        就可以写出伪代码

        node//根节点

        main(node.left)//左节点

        mian(node.right)//右结点

        但是需要求和,此时就进行2棵树的合并操作。

        1.递归解决,先合并跟节点,在递归合并左节点,递归合并右节点

public TreeNode mergeTrees (TreeNode t1, TreeNode t2) {
        // write code here
        //判断是否为空树
        if(t1==null) {
            return t2;
        }
        if(t2==null) {
            return t1;
        }
        //根
        TreeNode res = new TreeNode(t1.val+t2.val);
        //左
        res.left = mergeTrees(t1.left,t2.left);
        //右
        res.right = mergeTrees(t1.right,t2.right);
        return res;
    }

2.判断是不是二叉搜索树(考过)

给定一个二叉树根节点,请你判断这棵树是不是二叉搜索树。

二叉搜索树满足每个节点的左子树上的所有节点均小于当前节点且右子树上的所有节点均大于当前节点。

例:

数据范围:节点数量满足 1≤n≤104  ,节点上的值满足−231≤val≤231−1 

思路:二叉平衡树即左小于根,根小于右。很容易想到左根右 中序遍历。

 int pre = Integer.MIN_VALUE;
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param root TreeNode类 
     * @return bool布尔型
     */
    public boolean isValidBST (TreeNode root) {
        // write code here
        //判断哪种遍历方式,可以看出来是左根右即中序遍历,使用递归方式进行解决
        if(root==null) {
            return true;
        }
        //左, 递归好处就是找到最左侧节点
        if(!isValidBST(root.left)) {
            return false;
        }
        //根,递归完成之后找到最左侧进行处理,判断上一个元素和当前元素进行比较,如果前面一个元素比当前值大,那就返回false
        if(pre>root.val) {
            return false;
        }
        //进行值替换
        pre = root.val;
        //右
        return isValidBST(root.right);
    }

思路讲解:递归实现,按照中序遍历即可,区别就是在根节点的处理方式上,pre初始化其实就是最左侧的一个节点的值,将最左侧的值替换给pre,逐级进行左根右的判断。

3. 判断是不是平衡二叉树(考过)

输入一棵节点数为 n 二叉树,判断该二叉树是否是平衡二叉树。

在这里,我们只需要考虑其平衡性,不需要考虑其是不是排序二叉树

平衡二叉树(Balanced Binary Tree),具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

样例解释:

样例二叉树如图,为一颗平衡二叉树

注:我们约定空树是平衡二叉树。

解题思路:此问题是求高度差,按照遍历方式来讲,是跟左右的处理方式,也就是前序遍历。

也就可以使用递归方式解决,递归前提就是获取根节点的左右最大高度差,可以参考7.获取高度差方式。

然后每个节点进行递归判断,即可获取到结果。

 public boolean IsBalanced_Solution (TreeNode pRoot) {
        // write code here
        //如果是空树,则是平衡二叉树,平衡就是节点高度不超过1
        if(pRoot==null) {
            return true;
        }
        //如何判断高度不高于1,则要找到左节点的最大高度,右要找到右侧最大高度进行比较
        int left = getMaxPath(pRoot.left);
        int right = getMaxPath(pRoot.right);
        //判断高度差,如果高于1,返回false
        if(left-right>1||right-left>1) {
            return false;
        }
        //根节点判断完了,则要判断左右节点的高度差
        return IsBalanced_Solution(pRoot.left)&&IsBalanced_Solution(pRoot.right);
    }

    //获取最大高度的算法,一可以用递归,二可以用队列,接下来用递归进行实现
    public int getMaxPath(TreeNode node) {
        //空情况下返回0
        if(node==null) {
            return 0;
        }
        //获取左侧
        int left = getMaxPath(node.left);
        int right = getMaxPath(node.right);
        return left>right?left+1:right+1;//这里加上本身节点的值
    }

4. 判断是不是完全二叉树(暂未考过)

给定一个二叉树,确定他是否是一个完全二叉树。

完全二叉树的定义:若二叉树的深度为 h,除第 h 层外,其它各层的结点数都达到最大个数,第 h 层所有的叶子结点都连续集中在最左边,这就是完全二叉树。(第 h 层可能包含 [1~2h] 个节点)

思路:其中的说节点左节点必须有内容,为什么可以使用队列,先进先出特性,一级一级的进行判断,只要存在一个节点左节点为空,还存在右节点情况下,就可以判断是否是完全二叉树。

public boolean isCompleteTree (TreeNode root) {
        // write code here
        //空数处理
        if(root==null) {
            return true;
        }
        //按照队列的方式入队列
        Queue<TreeNode> q = new LinkedList<TreeNode>();
        //将树存入
        q.offer(root);
        //定义临时bolean,记录左节点为空情况。
        boolean leftNull = false;
        //遍历队列
        while(!q.isEmpty()) {
            //出队列
            TreeNode temp = q.poll();
            //判断temp是否为空
            if(temp==null) {
                leftNull = true;
                //接着遍历,都为空就接着遍历
                continue;
            }
            //上面不为空,判断左测是否为空,为空就直接返回false
            if(leftNull) {
                return false;
            }
            //将左节点入队列,注意一定是先入左,队列先进先出
            q.offer(temp.left);
            //再将右队列入队列
            q.offer(temp.right);
        }
        return true;
    }

5. 求二叉树的层序遍历

给定一个二叉树,返回该二叉树层序遍历的结果,(从左到右,一层一层地遍历)
例如:
给定的二叉树是{3,9,20,#,#,15,7},
 


该二叉树层序遍历的结果是
[
[3],
[9,20],
[15,7]

]

思路:需要一层一层的输出,自上往下的输出。利用队列先进先出的特性,每一层一层的遍历,如何判断是那一层便是队列的问题所在,所以先进行根节点也就是3的输出,然后将9和20入队列;下次的时候判断队列长度多少,进行循环出队列。

public ArrayList<ArrayList<Integer>> levelOrder (TreeNode root) {
        // write code here
        ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
        if(root==null) {
            return res;
        }
        Queue<TreeNode> q = new LinkedList<>();
        q.offer(root);
        while(!q.isEmpty()) {
            ArrayList<Integer> list = new ArrayList<Integer>();
            int size = q.size();
            for(int i=0;i<size;i++) {
                TreeNode temp = q.poll();
                list.add(temp.val);
                if(temp.left!=null) {
                    q.offer(temp.left);
                }
                if(temp.right!=null) {
                    q.offer(temp.right);
                }
            }
            res.add(list);
        }
        return res;
    }

6.按之字形顺序打印二叉树(考过)

   是上面求二叉树的层序遍历的变形。

给定一个二叉树,返回该二叉树的之字形层序遍历,(第一层从左向右,下一层从右向左,一直这样交替)
要求:空间复杂度:O(n),时间复杂度:O(n)

例如:
给定的二叉树是{1,2,3,#,#,4,5}
 


该二叉树之字形层序遍历的结果是

[

[1],

[3,2],

[4,5]

]

思路:和第五题区别在之字形打印,整体思路是一样的,唯一的区别如何之字形输出,可以定义一个变量,每层修改一下值,需要反转的行将list集合进行反转即可。

public ArrayList<ArrayList<Integer>> Print (TreeNode pRoot) {
        // write code here
        //返回的集合
        ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
        //1.空树判断
        if(pRoot==null) {
            return res;
        }
        //2.定义一个队列
        Queue<TreeNode> q = new LinkedList<>();
        //3.将树入队列
        q.offer(pRoot);//特殊说明,最好记住方法名称,面试有时候没有编译器,不自动带出,想不起来方法
        //4.定义一个变量,标志是否反转
        boolean reverse = true;
        //5.遍历队列
        while(!q.isEmpty()) {
            //进入一次修改一次
            reverse=!reverse;
            //定义一个局部变量用于处理每一行数据
            ArrayList<Integer> list = new ArrayList<Integer>();
            //看看队列中有多少元素
            int size = q.size();
            //因为队列先进先出,有一定顺序,所以循环出队列即可
            for(int i=0;i<size;i++) {
                //出队列
                TreeNode temp = q.poll();
                //放入集合中
                list.add(temp.val);
                //将左右节点入队列,为空情况排除
                if(temp.left!=null) {
                    q.offer(temp.left);
                }
                if(temp.right!=null) {
                    q.offer(temp.right);
                }
            }
            //特殊处理点,判断集合是否反转,反转将list进行反转
            if(reverse) {
                Collections.reverse(list);
            }
            //将集合放入结果集合中
            res.add(list);
        }
        return res;
    }

7.二叉树的最大深度

求给定二叉树的最大深度,

深度是指树的根节点到任一叶子节点路径上节点的数量。

最大深度是所有叶子节点的深度的最大值。

(注:叶子节点是指没有子节点的节点。)

思路:此处给出两种实现,第一种,使用递归,自下往上找。

                                           第二种,使用队列,自上往下算

递归实现:

public int maxDepth (TreeNode root) {
        // write code here
        //判断空树情况
        if(root==null) {
            return 0;
        }
        //先找到左侧的
        int left = maxDepth(root.left);
        //在找右侧的
        int right = maxDepth(root.right);
        //判断谁大
        return left>right?left+1:right+1;
    }

队列实现:模拟层序遍历的思想

public int maxDepth (TreeNode root) {
        // write code here
        //判断空树情况
        if(root==null) {
            return 0;
        }
       int res = 0;
        Queue<TreeNode> q = new LinkedList<TreeNode>();
        q.offer(root);
        while(!q.isEmpty()) {
            int size = q.size();
            for(int i=0;i<size;i++) {
                TreeNode temp = q.poll();
                if(temp.left!=null) {
                    q.offer(temp.left);
                }
                if(temp.right!=null) {
                    q.offer(temp.right);
                }
            }
            res++;
        }
        return res;
    }

8.二叉树中和为某一值的路径(一)

给定一个二叉树root和一个值 sum ,判断是否有从根节点到叶子节点的节点值之和等于 sum 的路径。

1.该题路径定义为从树的根结点开始往下一直到叶子结点所经过的结点

2.叶子节点是指没有子节点的节点

3.路径只能从父节点到子节点,不能从子节点到父节点

4.总节点数目为n


例如:
给出如下的二叉树,  sum=22,
 


返回true,因为存在一条路径 5→4→11→25→4→11→2的节点值之和为 22

数据范围:

1.树上的节点数满足 0≤100000≤n≤10000

2.每 个节点的值都满足 ∣val∣≤1000

要求:空间复杂度 O(n),时间复杂度 O(n)

进阶:空间复杂度 O(树的高度),时间复杂度O(n)

思路:求二叉树和,注意是从根到叶子节点上的和,此时需要考虑用什么办法解决?

          可以能想到一点的是,使用跟左右也就是前序进行遍历。假设遍历5->4这种数据,就要记录5+4的结果,就要考虑使用什么进行存储,也就是后放入的先出来,可以自然而然想到栈这种结构。

出栈情况下,既要把节点出栈,又要将值出栈,所以可以使用双栈这种结构。

public boolean hasPathSum (TreeNode root, int sum) {
        // write code here
        //1.判断是否为空数
        if(root==null) {
            return false;
        }
        //2.选用双栈结构,一个存储节点,一个存储每个节点的和
        Stack<TreeNode> sNode = new Stack<>();
        Stack<Integer> sVal = new Stack<>();
        //3.初始化数据
        sNode.add(root);
        sVal.add(root.val);
        //4.遍历栈
        while(!sNode.isEmpty()) {
            //4.1出栈
            TreeNode temp = sNode.pop();
            int cur_sum = sVal.pop();
            //4.2 判断是否满足条件了吗,左节点为空&右节点为空&cur_sum==sum
            if(temp.left==null&&temp.right==null&&cur_sum==sum) {
                //满足条件就进行返回
                return true;
            }
            //4.3否则说明左节点或者右结点里面有值,将其放入栈中,此时先放左或者先放右没有关系,个人习惯先放右节点,后放入左节点,这样出栈情况下也就是先出左节点
            if(temp.right!=null) {
                //两个栈同时存入数据
                sNode.add(temp.right);
                sVal.add(cur_sum+temp.right.val);
            }
            if(temp.left!=null) {
                sNode.add(temp.left);
                sVal.add(cur_sum+temp.left.val);
            }
        }
        return false;
    }

9.二叉搜索树与双向链表

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。如下图所示

数据范围:输入二叉树的节点数 0≤�≤10000≤n≤1000,二叉树中每个节点的值 0≤val≤1000
要求:空间复杂度O(1)(即在原树上操作),时间复杂度 O(n)

解题思路:判断是那种顺序,首先可以分析出来是左根右这种遍历,也就是中序遍历,一看到这种中序遍历可以立马想到下面这种结构体:

func main(TreeNode node){

        main(node.left);

        node.val;

        main(node.right);

}

但是返回结果是个双向链表,链表的移动是需要指针的,但是在树结构中如何移动,也就是cur = cur.right;

所以就会出现下面这种结构体:

TreeNode res = null;//和链表不太一样,不用设置头节点,初始化在下面步骤中进行

TreeNode cur = null;//其实就是链表算法中的指针。

func main(TreeNode node){

        main(node.left);
        
        cur.right = node;//指针修改
        node.left = cur;//指针修改
        cur = cur.right;//指针移动下一个节点上

        main(node.right);

}

所以最终代码就成了:

//返回的链表结构
    TreeNode res = null;
    //链表的指针
    TreeNode cur = null;
    public TreeNode Convert(TreeNode pRootOfTree) {
        //左根右 中序
        if(pRootOfTree==null) {
            return null;
        }
        //左
        Convert(pRootOfTree.left);
        //根
        //如果指针为空代表没数据,进行初始化
        if(cur==null) {
            res = pRootOfTree;
            cur = res;
        }else{
            cur.right = pRootOfTree;
            pRootOfTree.left = cur;
            cur = cur.right;//指针移动
        }
        //右
        Convert(pRootOfTree.right);
        return res;
    }

10.对称的二叉树

     给定一棵二叉树,判断其是否是自身的镜像(即:是否对称)
例如:                                 下面这棵二叉树是对称的
 


下面这棵二叉树不对称。
 

数据范围:节点数满足 0≤10000≤n≤1000,节点上的值满足 1000∣val∣≤1000

要求:空间复杂度 O(n),时间复杂度 O(n)

思路:是否对称:还是按照之前的想法,先判断是哪种遍历方式,可以看到不属于任何一种遍历方式,这个时候就要去考虑,怎么才能判断是否对称:可以很容易想到将原来树进行复制一份,使用第一颗树的左和第二颗树的右进行比较&&第一颗树的右节点和第二颗树的左进行进行比较

条件如下:

       两棵树都为空,返回true。

       两棵树有一个为空或者值不相等情况下,返回false。

 public boolean isSymmetrical (TreeNode pRoot) {
        // write code here
        //1.空树是对称的
        if(pRoot==null) {
            return true;
        }
        //两棵树进行比较
        return isSymmetrical(pRoot,pRoot);
    }

    public boolean isSymmetrical(TreeNode node1,TreeNode node2) {
        //当两棵树同时为空,证明是ok的
        if(node1==null&&node2==null) {
            return true;
        }
        //如果有一棵树为空,一颗不为空,证明不对称
        //两个节点的值不一样也不对称
        if (node1==null||node2==null||node1.val!=node2.val) {
            return false;
        }
        //将第一棵树左节点和第二棵树右节点进行比较+第一棵树右节点和第二棵树左节点比较的结果&就可求出来
        return isSymmetrical(node1.left,node2.right)&isSymmetrical(node1.right,node2.left);
    }

11.二叉树的镜像

操作给定的二叉树,将其变换为源二叉树的镜像。

数据范围:二叉树的节点数 0≤10000≤n≤1000 , 二叉树每个节点的值 0≤10000≤val≤1000

要求: 空间复杂度 O(n) 。本题也有原地操作,即空间复杂度O(1) 的解法,时间复杂度 O(n)

比如:

源二叉树

镜像二叉树

思路解析:

   1.镜像二叉树其实就是将左节点所有元素复制到右边。

   2.还是分析使用什么遍历方式,可以分析出来是根左右,只是有部分不同,思想还是一样的。

 代码:

public TreeNode Mirror (TreeNode pRoot) {
        // write code here
        //根左右
        if(pRoot==null) {
            return pRoot;
        }
        //根左右-只是变化了一下变成了根右左了
        TreeNode res = new TreeNode(pRoot.val);
        res.left = Mirror(pRoot.right);
        res.right = Mirror(pRoot.left);
        return res;
    }

12.二叉搜索树的最近公共祖先(考过)

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。

1.对于该题的最近的公共祖先定义:对于有根树T的两个节点p、q,最近公共祖先LCA(T,p,q)表示一个节点x,满足x是p和q的祖先且x的深度尽可能大。在这里,一个节点也可以是它自己的祖先.

2.二叉搜索树是若它的左子树不空,则左子树上所有节点的值均小于它的根节点的值; 若它的右子树不空,则右子树上所有节点的值均大于它的根节点的值

3.所有节点的值都是唯一的。

4.p、q 为不同节点且均存在于给定的二叉搜索树中。

数据范围:

3<=节点总数<=10000

0<=节点值<=10000

如果给定以下搜索二叉树: {7,1,12,0,4,11,14,#,#,3,5},如下图:

输入:

{7,1,12,0,4,11,14,#,#,3,5},1,12

返回值:

7

说明:

节点1 和 节点12的最近公共祖先是7   

解题思路:二叉搜索树的特点是:左子树比根小,右子树比根大。

                  此时公共祖先大概率在其中一个根节点上,所以遍历方式就是跟左右即前序遍历,可以考虑递归进行处理。只是变形的第一点需要考虑截至条件,什么时候截至呢?

只有当根节点在p和q的的范围内代表符合要求

//也就是处理根逻辑

if((root.val>=p&&root.val<=q)||(root.val<=p&&root.val>=q)) {

        return root.val;//此时也就是最近的公共祖先。

}

//左逻辑,什么情况在左侧呢,其实就是节点值都比p和q大的情况。

//右逻辑,其实就是节点值都比p和q小的时候。

public int lowestCommonAncestor (TreeNode root, int p, int q) {
        // write code here
        if(root==null) {
            return -1;
        }
        //此时判断是否当前节点符合要求。
        if((root.val>=p&&root.val<=q)||(root.val<=p&&root.val>=q)) {
            return root.val;
        }else if(root.val<=p&&root.val<=q) {
            //同时小的情况下,说明在右侧
            return lowestCommonAncestor(root.right,p,q);
        }else{
            //同时大的情况下,说明在左侧
            return lowestCommonAncestor(root.left,p,q);
        }
    }

13. 在二叉树中找到两个节点的最近公共祖先

给定一棵二叉树(保证非空)以及这棵树上的两个节点对应的val值 o1 和 o2,请找到 o1 和 o2 的最近公共祖先节点。

数据范围:树上节点数满足 1≤n≤105  , 节点值val满足区间 [0,n)

要求:时间复杂度 O(n)

注:本题保证二叉树中每个节点的val值均不相同。

如当输入{3,5,1,6,2,0,8,#,#,7,4},5,1时,二叉树{3,5,1,6,2,0,8,#,#,7,4}如下图所示:

所以节点值为5和节点值为1的节点的最近公共祖先节点的节点值为3,所以对应的输出为3。

节点本身可以视为自己的祖先

思路:此题比12题略难,就是左节点和右结点没有规律。

          思考方式是一致的,也是跟左右的判断逻辑,只是不能按照之前的方式进行求解了。

          所以可以考虑从根出发,找左侧节点等于o1或者o2得节点,从右侧节点等于o1或者o2得值,如果找到,当前节点就是最近得公共祖先。

          根处理逻辑稍微复杂点:找到一个节点和o1或者o2相等,返回左节点或者是右节点

                                                 如果左节点一直没有找到,则证明最近的公共节点就是右节点,否则是左节点

          //根逻辑

        if(node.val==o1||node.val==02) {

               return node.val;

        }

         //左逻辑

         int left = func(node.left,o1,o2);

        //右逻辑

         int right = func(node.right,o1,o2);

public int lowestCommonAncestor (TreeNode root, int o1, int o2) {
        // write code here
        //根左右
        if(root==null) {
            return -1;
        }
        //根逻辑
        if(root.val==o1||root.val==o2) {
            return root.val;
        }
        //左逻辑,其实就是找左节点符合的元素
        int left = lowestCommonAncestor(root.left,o1,o2);
        //右逻辑
        int right = lowestCommonAncestor(root.right,o1,o2);
        //此时判断左侧没有找到的情况
        if(left==-1) {
            return right;
        }
        if(right==-1) {
            return left;
        }
        return root.val;
    }

14.重建二叉树

给定节点数为 n 的二叉树的前序遍历和中序遍历结果,请重建出该二叉树并返回它的头结点。

例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建出如下图所示。

提示:

1.vin.length == pre.length

2.pre 和 vin 均无重复元素

3.vin出现的元素均出现在 pre里

4.只需要返回根结点,系统会自动输出整颗树做答案对比

数据范围:n≤2000,节点的值 −10000≤val≤10000

要求:空间复杂度O(n),时间复杂度 O(n)

有两种解决方案:递归+栈都可以实现

递归实现:

public TreeNode reConstructBinaryTree (int[] preOrder, int[] vinOrder) {
        // write code here
        if(preOrder.length==0||vinOrder.length==0) {
            return null;
        }
        //前序是根左右,中序是左根右,可以知道preOrder[0]即为整棵树根节点
        TreeNode res = new TreeNode(preOrder[0]);

        for(int i=0;i<vinOrder.length;i++) {
            //找到中序树根相等得情况
            if(vinOrder[i]==preOrder[0]) {
                //相等得前面都是左边得数据
                res.left = reConstructBinaryTree(Arrays.copyOfRange(preOrder,1,i+1),Arrays.copyOfRange(vinOrder,0,i));
                //后面都是右边得数据
                res.right = reConstructBinaryTree(Arrays.copyOfRange(preOrder,i+1,preOrder.length),Arrays.copyOfRange(vinOrder,i+1,vinOrder.length));
                break;
            }
        }
        return res;
    }

栈实现:

public TreeNode reConstructBinaryTree (int[] preOrder, int[] vinOrder) {
        // write code here
        int n = preOrder.length;
        int m = vinOrder.length;
        if(n==0||m==0) {
            return null;
        }
        Stack<TreeNode> s = new Stack<>();
        TreeNode res = new TreeNode(preOrder[0]);
        TreeNode cur = res;
        for(int i=1,j=0;i<n;i++) {
            if(cur.val!=vinOrder[j]) {
                cur.left = new TreeNode(preOrder[i]);
                s.add(cur);
                cur = cur.left;
            }else{
                j++;
                while(!s.isEmpty()&&s.peek().val==vinOrder[j]) {
                    cur = s.pop();
                    j++;
                }
                cur.right = new TreeNode(preOrder[i]);
                cur = cur.right;
            }
        }
        return res;
    }

15.输出二叉树的右视图

如输入[1,2,4,5,3],[4,2,5,1,3]时,通过前序遍历的结果[1,2,4,5,3]和中序遍历的结果[4,2,5,1,3]可重建出以下二叉树:

所以对应的输出为[1,3,5]。

思路解析:层级遍历问题,可以想到使用栈或者队列

栈实现:

public int[] printView(TreeNode node) {
        if(node==null) {
            return new int[0];
        }
        //使用map结构,key存储层级,value存储右边得值
        Map<Integer,Integer> map = new HashMap<>();
        Stack<TreeNode> s = new Stack<>();
        s.add(node);
        Stack<Integer> sDepth = new Stack<>();
        sDepth.add(0);
        while(!s.isEmpty()) {
            TreeNode temp = s.pop();
            int depth = sDepth.pop();
            if(map.get(depth)==null) {
                map.put(depth,temp.val);
            }
            //先入左,因为栈是先进后出
            if(temp.left!=null) {
                s.add(temp.left);
                sDepth.add(depth+1);
            }
            if(temp.right!=null) {
                s.add(temp.right);
                sDepth.add(depth+1);
            }
        }
        int[] res = new int[map.size()];
        for(int i=0;i<map.size();i++) {
            res[i] = map.get(i);
        }
        return res;
    }

队列实现

public int[] printView2(TreeNode node) {
        if (node == null) {
            return new int[0];
        }
        ArrayList<Integer> list = new ArrayList<>();
        //使用队列实现
        Queue<TreeNode> q = new LinkedList<>();
        q.offer(node);
        while(!q.isEmpty()) {
            int size = q.size();
            for(int i=0;i<size;i++) {
                //出队列
                TreeNode temp = q.poll();
                //当遍历到最后一个节点存储起来
                if(i==size-1) {
                    list.add(temp.val);
                }
                //入队列
                if(temp.left!=null) {
                    q.offer(temp.left);
                }
                if(temp.right!=null) {
                    q.offer(temp.right);
                }
            }
        }
        int[] res = new int[list.size()];
        for(int i=0;i<list.size();i++) {
            res[i] = list.get(i);
        }
        return res;
    }

总结:

二叉树算法面试题解题思路一共总结了三种:

1.递归解决

     递归情况下,判断是前序,后序还是中序遍历,加以变形即可。

     如何判断是前序,后序还是中序,一个快速的方法就是看根在哪。

      如果根在前面,就是前序,也就是我们常说的根左右

      如果根在中间,就是中序,也就是左根右。

      如果根在后面,就是后序,也就是左右根。

       想清楚什么顺序,按照这几个的递归能解决很多问题。

2.栈解决

     栈的特性是先进后出,在使用栈解决二叉树情况下,需要考虑好左节点先入还是右结点先入栈,要不结果有很大的不同。add()pop()。

       还有种情况需要双栈进行解决,比如要存储一个值,同时要存储节点,可以考虑双栈一起入栈出栈。

3.队列解决

    利用队列解决,比栈好的一点就是先进先出,比如层级输出问题可以这莫解决。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值