java实现对二叉树的各种操作

最近刷到挺多关于对二叉树相关操作的题目,刚开始还觉得挺难的,后来做了几次后发现有规律可循。方法不唯一但有时很难想到,特别是递归调用感觉看别人的代码挺简单的但是自己就是想不到转不过弯来,写个笔记以免自己忘了-_-
(题目大多来自牛客网或者力扣,可能有错误欢迎指出)
首先,二叉树基本结构为:

public class TreeNode {
      int val;
      TreeNode left;
      TreeNode right;
      TreeNode(int x) { val = x; }
  }

一、相同的树

如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的
给定两个二叉树,编写一个函数来检验它们是否相同:
递归调用:

public boolean isSameTree(TreeNode p, TreeNode q) {
        if(p==null && q==null) return true;
        if(p==null || q==null) return false;
        if(p.val !=q.val) return false;
        return isSameTree(p.left,q.left) && isSameTree(p.right,q.right);
    }

二、对称二叉树

如果一个树的左子树与右子树镜像对称,那么这个树是对称的。
给定一个二叉树,检查它是否是镜像对称的。这就相当于检查两棵树是否镜像对称:即根结点相同,左子树与另外一棵树的右子树相同

    public boolean isSymmetric(TreeNode root) {
        return isMirror(root,root);
    }
    public boolean isMirror(TreeNode p,TreeNode q){
        if(p==null && q==null) return true;
        if(p==null || q==null) return false;
        return (p.val==q.val)&&(isMirror(p.left,q.right)&&isMirror(p.right,q.left));
    }

三、求二叉树最大深度

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
给定一个二叉树,找出其最大深度。
(1)递归调用:

 public int maxDepth(TreeNode root) {
        if(root==null) return 0;
        int leftdepth=maxDepth(root.left);
        int rightdepth=maxDepth(root.right);
        return (leftdepth>=rightdepth? leftdepth :rightdepth)+1;
    }

(2)BFS广度优先搜索
沿着树的宽度依次遍历结点,即依次访问树的每一层

public int maxDepth(TreeNode root) {
        if(root==null) return 0;
        Queue<TreeNode> queue=new LinkedList<>();//创建队列存储树的每一层的结点
        int depth=0;
        queue.add(root);
        while(!queue.isEmpty()){
            depth++;
            int size=queue.size();
            for(int i=0;i<size;i++){//依次访问该层的所有结点
                TreeNode temp=queue.poll();
                if(temp.left!=null) queue.add(temp.left);
                if(temp.right!=null) queue.add(temp.right);
            }
        }
        return depth;
    }

四、二叉树的层次遍历

给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
例如:
给定二叉树 [3,9,20,null,null,15,7],

   3
  / \
 9  20
   /  \
  15   7

返回其自底向上的层次遍历为:
[[15,7], [9,20], [3]]

public List<List<Integer>> levelOrderBottom(TreeNode root) {
        Queue<TreeNode> queue =new LinkedList<>();//用来存储每层结点
        queue.add(root);
        List<List<Integer>> list=new LinkedList<>();
        if(root==null) return list;
        while(!queue.isEmpty()){
            list.add(0,new ArrayList<>());//将每层结点的数组插入到链表开头
            int size=queue.size();
            for(int i=0;i<size;i++){
                TreeNode tempNode=queue.poll();
                list.get(0).add(tempNode.val);//将每层结点的val依次添加到ArrayList
                if(tempNode.left!=null) queue.add(tempNode.left);
                if(tempNode.right!=null) queue.add(tempNode.right);
            }
        }
        return list;
    }

五、平衡二叉树

一棵高度平衡二叉树定义为:一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。
给定一个二叉树,判断它是否是高度平衡的二叉树。
自顶向下的递归:

class Solution {
    public boolean isBalanced(TreeNode root) {
        if(root==null) return true;
        return Math.abs(height(root.left)-height(root.right))<=1 && isBalanced(root.left) && isBalanced(root.right);
    }
    public int height(TreeNode root){//求树的高度
        if(root==null)return -1;
        return 1+Math.max(height(root.left),height(root.right));
    }
}

六、将有序数组转换为二叉搜索树

将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。
本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。
中序遍历:始终选择中间位置的左边元素作为根结点

class Solution {
    int [] nums;
    public TreeNode helper(int left,int right){
        if(left>right) return null;
        int p=(left+right)/2;
        /*始终选择中间位置的右边元素作为根结点
        int p=(left+right)/2;
        if((left+right)%2==1) ++p;*/
        TreeNode root=new TreeNode(nums[p]);
        root.left=helper(left,p-1);
        root.right=helper(p+1,right);
        return root;
    }
    public TreeNode sortedArrayToBST(int[] nums) {
        this.nums=nums;
        return helper(0,nums.length-1);
    }
}

七、路径总和

给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。
递归:

public boolean hasPathSum(TreeNode root, int sum) {
    if (root == null)
      return false;

    sum -= root.val;
    if ((root.left == null) && (root.right == null))
      return (sum == 0);
    return hasPathSum(root.left, sum) || hasPathSum(root.right, sum);
  }

作者:LeetCode
链接:https://leetcode-cn.com/problems/path-sum/solution/lu-jing-zong-he-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

迭代:

public boolean hasPathSum(TreeNode root, int sum) {
        if(root==null)    return false;
        Queue<TreeNode> nodeQueue=new LinkedList<>();
        Queue<Integer> sumQueue=new LinkedList<>();
        nodeQueue.add(root);
        sumQueue.add(root.val);
        while(!nodeQueue.isEmpty()){
            TreeNode tempNode=nodeQueue.poll();
            int tempSum=sumQueue.poll();
            if((tempNode.left==null)&&(tempNode.right==null)&&(tempSum==sum)) return true;
            if(tempNode.left!=null){
                nodeQueue.add(tempNode.left);
                sumQueue.add(tempSum+tempNode.left.val);
            }
             if(tempNode.right!=null){
                nodeQueue.add(tempNode.right);
                sumQueue.add(tempSum+tempNode.right.val);
            }
        }
        return false;
    }

八、前序和中序重建二叉树

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

根据前序遍历的性质,第一个元素必然就是root
根据中序遍历的性质,root元素前面都是root的左子树,后面都是root的右子树。

import java.util.Arrays;
public class Solution {
     public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
         if(pre.length == 0) return null;
         TreeNode root = new TreeNode(pre[0]);
         if(pre.length == 1) return root;
         int index = 0;
         for(int i=0;i<in.length;i++){
             if(pre[0] == in[i]){
                 index = i;
                 break;
             }
         }
         root.left=reConstructBinaryTree(Arrays.copyOfRange(pre,1,index+1),Arrays.copyOfRange(in,0,index));
         root.right=reConstructBinaryTree(Arrays.copyOfRange(pre,index+1,pre.length),Arrays.copyOfRange(in,index+1,in.length));
         return root;
    }
}

欢迎补充

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值