美文网首页
剑指-树

剑指-树

作者: czczccz | 来源:发表于2021-03-25 16:30 被阅读0次

感谢K神

重建二叉树

根据前序遍历和后续遍历的结果重建二叉树。
思路:通过前序遍历的结果找到根节点,在后续遍历结果中分割树的左子树和右子树
难点:区间如何划分

//使用HashMap更快速的定位到节点在中序遍历的位置
    HashMap<Integer,Integer> inMaps = new HashMap<>();
    public TreeNode buildTree(int[] preorder, int[] inorder) {
      //为空判断
      for(int i = 0;i<inorder.length;i++)
      {
          inMaps.put(inorder[i],i);
      }
      return construct(preorder,0,0,inorder.length-1);
    }
    public TreeNode construct(int[] preorder,int root,int in_l,int in_r)
    {
        if(in_l>in_r) return null;
        //找到根节点的值
        int value = preorder[root];
        //新建节点
        TreeNode node = new TreeNode(value);
        //找到中序的位置
        int in_index = inMaps.get(value);
        //递归
/**
左子树的根节点为前一步加1
在中序遍历的起始位置为当前中序遍历的起始位置
在中序遍历的终止位置为当前根节点在中序遍历的位置-1
**/
        node.left = construct(preorder,root+1,in_l,in_index-1);
/**
右子树的根节点为前一步加1加上左子树的长度(in_index-in_l)
右子树在中序遍历的起始位置为当前in_index+1
右子树在中序遍历的终止位置为in_r
**/
        node.right = construct(preorder,root+in_index-in_l+1,in_index+1,in_r);
        return node;
    }

拓展:中序和后序也可以构成二叉树

剑指 Offer 26. 树的子结构

思路:如何定义子结构是相等的
1:如果当前两个节点的值是相等的,那么就递归两者的左和右,直到一方为空,或者两方皆空的时候,再判断。
2:两个节点的值不等,false

   public boolean isSubStructure(TreeNode A, TreeNode B) {
        //判断左子树是不是,右子树是不是
        boolean result = false;

        if(A!=null && B!=null){
            if(A.val == B.val) result = isSubTree(A,B);
            if(!result)
            result = isSubStructure(A.left,B);
            if(!result)
            result = isSubStructure(A.right,B);
        }
        return result;
    }

    public boolean isSubTree(TreeNode A ,TreeNode B)
    {
        if(A==null && B==null) return true;
        if(A!=null && B == null) return true;
        if(A==null && B!=null) return false;
        if(A.val != B.val) return false;
        return isSubTree(A.left,B.left) && isSubTree(A.right,B.right);
    }

二叉树的镜像

请完成一个函数,输入一个二叉树,该函数输出它的镜像。


image.png

思路:翻转二叉树,反转子树的二叉树,只有后序遍历可以操纵左右节点
非递归:

class Solution {
    public TreeNode mirrorTree(TreeNode root) {
        if(root == null) return null;
        Stack<TreeNode> stack = new Stack<>() {{ add(root); }};
        while(!stack.isEmpty()) {
            TreeNode node = stack.pop();
            if(node.left != null) stack.add(node.left);
            if(node.right != null) stack.add(node.right);
//交换指向
            TreeNode tmp = node.left;
            node.left = node.right;
            node.right = tmp;
        }
        return root;
    }
}

对称的二叉树

剑指 Offer 28. 对称的二叉树
请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。

public boolean isSame(TreeNode L,TreeNode R)
{
    if(L==null && R == null) return true;
    if(L==null && R == null) return false;
    if(L.val != R.val) return false;
    return isSame(L.left,R.right) && isSame(L.right,R.left);
}

剑指 Offer 32 - III. 从上到下打印二叉树 III

重点在于确定奇偶

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<>();
        List<List<Integer>> res = new ArrayList<>();
        if(root != null) queue.add(root);
        while(!queue.isEmpty()) {
            LinkedList<Integer> tmp = new LinkedList<>();
            for(int i = queue.size(); i > 0; i--) {
                TreeNode node = queue.poll();
                if(res.size() % 2 == 0) tmp.addLast(node.val); // 偶数层 -> 队列头部
                else tmp.addFirst(node.val); // 奇数层 -> 队列尾部
                if(node.left != null) queue.add(node.left);
                if(node.right != null) queue.add(node.right);
            }
            res.add(tmp);
        }
        return res;
    }
}

剑指 Offer 37. 序列化二叉树

public class Codec {
//序列化,传入二叉树,输出层序遍历结果,null也得输出
    public String serialize(TreeNode root) {
        if(root == null) return "[]";
        StringBuilder res = new StringBuilder("[");
        Queue<TreeNode> queue = new LinkedList<>() {{ add(root); }};
        while(!queue.isEmpty()) {
            TreeNode node = queue.poll();
            if(node != null) {
                res.append(node.val + ",");
                queue.add(node.left);
                queue.add(node.right);
            }
            else res.append("null,");
        }
//移除最后一个,号
        res.deleteCharAt(res.length() - 1);
        res.append("]");
        return res.toString();
    }

    public TreeNode deserialize(String data) {
//空判断
        if(data.equals("[]")) return null;
//由,号分割,并且[,和]都移除了,目前val里面都是值和null
        String[] vals = data.substring(1, data.length() - 1).split(",");
//建立根节点
        TreeNode root = new TreeNode(Integer.parseInt(vals[0]));
//根节点入队列
        Queue<TreeNode> queue = new LinkedList<>() {{ add(root); }};
//i用来遍历字符串数组
        int i = 1;
        while(!queue.isEmpty()) {
//取出根节点
            TreeNode node = queue.poll();
//获取当前根节点的左节点,不为空的话,就左指向,并且加入队列
            if(!vals[i].equals("null")) {
                node.left = new TreeNode(Integer.parseInt(vals[i]));
                queue.add(node.left);
            }
//,右节点,同上
            i++;
            if(!vals[i].equals("null")) {
                node.right = new TreeNode(Integer.parseInt(vals[i]));
                queue.add(node.right);
            }
            i++;
        }
        return root;
    }
}

剑指 Offer 54. 二叉搜索树的第k大节点

二叉搜索树的中序遍历是底层序列,所以先把中序遍历的结果保存到list里面,然后取出第size-k个就好了

剑指 Offer 55 - I. 二叉树的深度

    public int maxDepth(TreeNode root) {
        return root==null?0:depth(root);
    }
    public int depth(TreeNode node)
    {
        if(node == null) return 0;
        return Math.max(depth(node.left),depth(node.right))+1;
    }

剑指 Offer 55 - II. 平衡二叉树

判断当前节点的左深度-右深度的绝对值是否超过1 ,不超过就递归再看左和右

class Solution {
    public boolean isBalanced(TreeNode root) {
        if(root == null) return true;
        return Math.abs(depth(root.left) - depth(root.right))<=1 && isBalanced(root.left) && isBalanced(root.right);
    }
    public int depth(TreeNode node)
    {
        if(node == null) return 0;
        return Math.max(depth(node.left),depth(node.right))+1;
    }
}

剑指 Offer 68 - I. 二叉搜索树的最近公共祖先

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
         while(root != null) {
            if(root.val < p.val && root.val < q.val) // p,q 都在 root 的右子树中
                root = root.right; // 遍历至右子节点
            else if(root.val > p.val && root.val > q.val) // p,q 都在 root 的左子树中
                root = root.left; // 遍历至左子节点
            else break;
        }
        return root;
    }
}

剑指 Offer 68 - II. 二叉树的最近公共祖先

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null) return null; // 如果树为空,直接返回null
        if(root == p || root == q) return root; // 如果 p和q中有等于 root的,那么它们的最近公共祖先即为root(一个节点也可以是它自己的祖先)
        TreeNode left = lowestCommonAncestor(root.left, p, q); // 递归遍历左子树,只要在左子树中找到了p或q,则先找到谁就返回谁
        TreeNode right = lowestCommonAncestor(root.right, p, q); // 递归遍历右子树,只要在右子树中找到了p或q,则先找到谁就返回谁
        if(left == null) return right; // 如果在左子树中 p和 q都找不到,则 p和 q一定都在右子树中,右子树中先遍历到的那个就是最近公共祖先(一个节点也可以是它自己的祖先)
        else if(right == null) return left; // 否则,如果 left不为空,在左子树中有找到节点(p或q),这时候要再判断一下右子树中的情况,如果在右子树中,p和q都找不到,则 p和q一定都在左子树中,左子树中先遍历到的那个就是最近公共祖先(一个节点也可以是它自己的祖先)
        else return root; //否则,当 left和 right均不为空时,说明 p、q节点分别在 root异侧, 最近公共祖先即为 root
    }
}

面试题34. 二叉树中和为某一值的路径

class Solution {
//记录结果
    LinkedList<List<Integer>> res = new LinkedList<>();
//记录路径
    LinkedList<Integer> path = new LinkedList<>(); 
    public List<List<Integer>> pathSum(TreeNode root, int sum) {
        recur(root, sum);
        return res;
    }
    void recur(TreeNode root, int tar) {
        if(root == null) return;
        path.add(root.val);
        tar -= root.val;
//保证是到叶节点的
        if(tar == 0 && root.left == null && root.right == null)
            res.add(new LinkedList(path));
//采用先序遍历
        recur(root.left, tar);
        recur(root.right, tar);
//移除最后加入的
        path.removeLast();
    }
}

相关文章

  • 剑指-树

    感谢K神 重建二叉树[https://leetcode-cn.com/problems/zhong-jian-er...

  • 《剑指Offer》树

    1 基础知识 树的操作会涉及到大量指针,因此与树有关的面试题都不太容易。当面试官想考察应聘者在有复杂指针操作的情况...

  • 剑指offer----树

    重建二叉树:根据前序和中序遍历的结果重建二叉树。假设输入的遍历结果都不含有重复的数字。 二叉树的下一个节点:给定一...

  • 剑指offer之(树)

    树 写这个文章的目的是为了记录,好背。 树的遍历和树的深度是基础,很多题都是在遍历的基础上加些限制条件,下边题目的...

  • 剑指offer--树

    参考:https://www.cnblogs.com/qmillet/p/12000557.html 题一:【重建...

  • 剑指offer-树

  • 【剑指Offer】017——树的子结构(树)

    题目描述 输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构) 解题思路 要...

  • [剑指offer] 树的子结构

    题目描述 输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构) 解题思路 递...

  • 剑指offer 28 树是否镜像

    我的思路是将左子树先swap, 再检查和右子树是否一样, 显然这样修改了原来的数据结构. 更好的思路是, 检查l-...

  • 剑指offer学习笔记:8.4 树

    面试题58:二叉树的下一个节点给定一个二叉树和其中一个节点,如何找到中序遍历顺序的下一个节点?树中的节点除了有两个...

网友评论

      本文标题:剑指-树

      本文链接:https://www.haomeiwen.com/subject/kywjhltx.html