二叉树--力扣算法

1、 重建二叉树

输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。

public TreeNode buildTree(int[] preorder, int[] inorder) {
   
        if ( preorder.length== 0)
            return null;
        int rootval = preorder[0], rootIndex = 0;
        for(int i=0;i<preorder.length;i++){
   //找中序序列中的根节点的索引
            if(inorder[i]==rootval ){
   
                rootIndex=i;
                break;
            }
        }
         TreeNode s=new TreeNode(rootval);
   //Arrays.copyOfRange(T[ ] original,int from,int to)  将一个原始的数组original,从下标from开始复制,复制到上标to,生成一个新的数组       
s.left=buildTree(Arrays.copyOfRange(preorder,1,1+rootIndex),Arrays.copyOfRange(inorder,0,rootIndex));        s.right=buildTree(Arrays.copyOfRange(preorder,1+rootIndex,preorder.length),Arrays.copyOfRange(inorder,rootIndex+1,preorder.length));
           return s;
    
    }

思路:这个效率高,但只能使用与前中序列没有重复的元素
root root+1 i-left+1+root
前序数组 根 | 左子树 | 右子树
left i-1 i i+1 right
中序数组 左子树 | 根 | 右子树
i - left + root + 1含义为 根节点索引 + 左子树长度 + 1

 int[] preorder;
    HashMap<Integer, Integer> dic = new HashMap<>();
    public TreeNode buildTree(int[] preorder, int[] inorder) {
   
        this.preorder = preorder;
        //将中序的值放入hashmap
        for(int i = 0; i < inorder.length; i++)
            dic.put(inorder[i], i);
        return recur(0, 0, inorder.length - 1);
    }
    //构建树
    TreeNode recur(int root, int left, int right) {
   
        if(left > right) return null;                          // 递归终止
        TreeNode node = new TreeNode(preorder[root]);          // 建立根节点
        int i = dic.get(preorder[root]);                       // 划分根节点、左子树、右子树
        node.left = recur(root + 1, left, i - 1);              // 开启左子树递归
        node.right = recur(root + i - left + 1, i + 1, right); // 开启右子树递归
        return node;                                           // 回溯返回根节点
    }

2、平衡二叉树

输入一棵二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。
给定二叉树 [3,9,20,null,null,15,7],返回true
在这里插入图片描述

思路: 后序遍历 + 剪枝 (从底至顶)
对二叉树做后序遍历,从底至顶返回子树深度,判定某子树不是平衡树则 “剪枝” ,直接向上返回。
在这里插入图片描述

//为-1说明不是平衡二叉树
public boolean isBalanced(TreeNode root) {
   
        return cont(root) != -1;
    }
    private int cont(TreeNode root){
   
        if(root==null) return 0;
        int left=cont(root.left);
         if(left == -1) return -1;
        int right=cont(root.right);
        if(right == -1) return -1;
   return Math.abs(left - right) < 2 ? Math.max(left, right) + 1 : -1;
    }

思路:先序遍历 + 判断深度 (从顶至底)会产生大量重复计算,时间复杂度较高
通过比较某子树的左右子树的深度差 <= 1 是否成立,来判断某子树是否是二叉平衡树。若所有子树都平衡,则此树平衡。


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);
    }

    private int depth(TreeNode root) {
   
        if (root == null) return 0;
        return Math.max(depth(root.left), depth(root.right)) + 1;
    }

3、 对称的二叉树

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

例如,二叉树 [1,2,2,3,4,4,3] 是对称的。
1
/
2 2
/ \ /
3 4 4 3
思路:找两个节点往下判断是否是对称的

 public boolean isSymmetric(TreeNode root) {
   
       return root == null ? true : recur(root.left, root.right);
    }
    //对称 左节点的左节点 && 右节点的右节点   左节点的右节点 && 右节点的左节点
      boolean recur(TreeNode L, TreeNode R) {
   
        if(L == null && R == null) return true;
        if(L == null || R == null || L.val != R.val) return false;
        return recur(L.left, R.right) && recur(L.right, R.left);
    }

4、二叉树的镜像

请完成一个函数,输入一个二叉树,该函数输出它的镜像
在这里插入图片描述

**思路1:**使用递归的思想 根节点的左右节点兑换

public TreeNode mirrorTree(TreeNode root) {
   
        if(root==null){
   
          return null;
      }
      TreeNode tmp=root.left;
      root.left=mirrorTree(root.right);
      root.right=mirrorTree(tmp); 
     return root;
    }

**思路:**使用额外的空间-栈

public TreeNode mirrorTree(TreeNode root) {
   
        if(root == null) return null;
        Stack<TreeNode> stack = 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值