二叉树的习题练习

1、二叉树的基本操作

构建二叉树的类

public class BinaryTree{
    static class TreeNode {
        public char val;
        public TreeNode left;
        public TreeNode right;

        public TreeNode(char val) {
            this.val = val;
        }
    }
    public TreeNode createTree() {

        TreeNode A = new TreeNode('A');
        TreeNode B = new TreeNode('B');
        TreeNode C = new TreeNode('C');
        TreeNode D = new TreeNode('D');
        TreeNode E = new TreeNode('E');
        TreeNode F = new TreeNode('F');
        TreeNode G = new TreeNode('G');
        TreeNode H = new TreeNode('H');

        A.left = B;
        A.right = C;
        B.left = D;
        B.right = E;
        C.left = F;
        C.right = G;
        E.right = H;

        return A;
    }
}

1.1获取树中结点的个数

思路:获取树中结点个数 = 获取树中左子树结点个数 + 右子树结点个数。递归返回的标志在于,遇到了一个结点,它没有左右子树,则返回。

public int size(TreeNode root){
    if(root == null){
        return 0;
    }
    
    return size(root.left) + size(root.right) + 1;
}

1.2获取叶子结点的个数

思路:获取树中叶子结点个数 = 获取树中左子树叶子结点个数 + 右子树叶子结点个数。遇到叶子则返回1,否则就一直递归左右子树。

int getLeafNodeCount(TreeNode root) {
        //左右都为空,即为叶子
        if (root == null) {
            return 0;
        }
        if (root.left == null && root.right == null) {
            return 1;
        }
        return getLeafNodeCount(root.left) + getLeafNodeCount(root.right);
    }

1.3获取第k层结点的个数

思路:从root开始递归,每递归一次,k-=1,递归终止条件是k==1。递归的内容是求k层结点,可以转化为求k-1层结点的个数。

int getk(TreeNode root,int k){
        if (root==null){
            return 0;
        }
        if (k==1){
            return 1;
        }
        return getk(root.left,k-1) + getk(root.right,k-1)
    }

1.4获取二叉树的高度

思路:整棵树的高度 = max(左子树高度 , 右子树高度) + 1。递归终止条件为左树和右树都为null,就返回,此时是max(0 + 0) + 1即返回1。

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

1.5检测值为value的元素是否存在

思路:遍历,判断是否相等。如果当前根不是,就在左子树找,左子树找完了没有,就在右子树找。如果都没有就表示值不存在。

TreeNode find(TreeNode root, char val) {
        if (root == null) {
            return null;
        }
        if (root.val == val) {
            return root;
        }

        TreeNode ret1 = find(root.left, val);
        if (ret1 != null) {
            return ret1;    //找到了,不去右边了
        }

        TreeNode ret2 = find(root.right, val);
        if (ret2 != null) {
            return ret2;
        }
        return null;
    }

1.6层序遍历二叉树

思路:从上到下,从左到右,一次遍历。拿一个队列来接收,先进先出,按照根左右的顺序存入,并输出

void levelOrder(TreeNode root) {
    if(root == null){
        return ;
    }
    //先放先出,根左右放入,根左右打印
    Queue<TreeNode> queue = new LinkedList<>();
    queue.offer(root);
    while (!queue.isEmpty()){
        //打印输出queue里的值
        TreeNode cur = queue.poll();
        System.out.print(cur.val + " ");
        //存入左
        if (cur.left != null){
            queue.offer(cur.left);
        }
        //存入右
        if (cur.right != null){
            queue.offer(cur.right);
        }
    }
}

 1.7判断一个二叉树是不是完全二叉树

思路:通过判断队列中有无非空元素

// 判断一棵树是不是完全二叉树
boolean isCompleteTree(TreeNode root) {
    if (root == null) {
        return true;
    }
    Queue<TreeNode> queue = new LinkedList<>();
    queue.offer(root);

    while (!queue.isEmpty()) {
        TreeNode cur = queue.poll();
        if (cur != null) {
            //存入左右元素
            queue.offer(cur.left);
            queue.offer(cur.right);
        } else {
            break;//如果cur为空,就结束循环
        }
    }
    //判断队列当中是否有非空元素,有则不是完全,没有则是完全
    while (!queue.isEmpty()) {
        //一个元素一个元素的出队,来判断有没有非空元素
        TreeNode tmp = queue.peek();
        //有空直接出
        if (tmp == null){
            queue.poll();
        }else{
            //有元素直接返回false,不是完全二叉树
            return false;
        }
    }
    //如果队列走完了,说明全是空,则必是完全二叉树
    return true;
}

2、二叉树的OJ题

2.1检查两颗树是否相同。

思路:1.确定结构上相同;2.确定结点值上相同。要判断两棵树是否相同,需判断根是否相同,左子树是否相同,右子树是否相同

public boolean isSameTree(TreeNode p, TreeNode q) {
    //给根做文章,判断根
    //一个为空
    if (p == null && q != null || p != null && q == null) {
        return false;
    }
    //两个都为空
    if (p == null && q == null) {
        return true;
    }
    //两个都不为空,比值
    if (p.val != q.val){
        return false;
    }
    //走到这,两个根结点是一样的了,就要递归判断两颗树的左右子树是否相同
    return isSameTree(p.left,q.left) && isSameTree(p.right,q.right);
}

2.2另一颗树的子树。

 思路:和根结点比较,如果不相同,那么再和根结点的左右子树相比,如果全部都不相同则返回false

public boolean isSubtree(TreeNode root, TreeNode subRoot) {
    if (root == null || subRoot == null){
        return false;
    }
    if (isSameTree(root,subRoot)){
        return true;
    }
    if (isSubtree(root.left,subRoot)){
        return true;
    }
    if (isSubtree(root.right,subRoot)){
        return true;
    }
    return false;
}

2.3翻转二叉树。

 思路:交换左右结点

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

    invertTree(root.left);
    invertTree(root.right);
    return root;
}

2.4判断一颗二叉树是否是平衡二叉树。

 思路:要判断每一个结点的左右子树高度。左树右树高度差<=1。

public boolean isBalanced(TreeNode root) {
        //最坏情况下,每个结点都要求高度
        //时间复杂度O(N)
        if (root == null) {
            return true;
        }
        int left = getHeight(root.left);
        int right = getHeight(root.right);
        return Math.abs(left - right) <= 1 && isBalanced(root.left) && 
isBalanced(root.right);
    }

public boolean isBalanced2(TreeNode root) {
        //缩短时间复杂度
        //一边求高度,一边判断平衡问题,如果已经不平衡了,则直接返回负数,节省时间
        //如果返回的值是正的,就平衡,返回的值是负数,就表示不平衡
        return maxDepth(root) >= 0;

    }

public int maxDepth(TreeNode root){
    if (root==null){
        return 0;
    }
    int leftHeight = maxDepth(root.left);
    int rightHeight = maxDepth(root.right);
    //满足平衡的情况
    if (leftHeight >= 0 && rightHeight >= 0 && Math.abs(leftHeight-rightHeight)<=1){
        //在这种情况下,才会返回真实的高度
        return Math.max(leftHeight,rightHeight) + 1;
    }else {
        //不满足平衡,就直接返回-1
        return -1;
    }
}

2.5对称二叉树。

思路:判断root的左树和root的右树是否对称。

public boolean isSymmetric(TreeNode root) {
    if (root == null) {
        return false;
    }

    return isSymmetricChild(root.left, root.right);
}

private boolean isSymmetricChild(TreeNode leftTree, TreeNode rightTree) {
    //一空一不空
    if (leftTree == null && rightTree != null || leftTree != null && rightTree == null) {
        return false;
    }
    //两个空树
    if (leftTree == null && rightTree == null) {
        return true;
    }
    //左右子树的值不相同
    if (leftTree.val != rightTree.val){
        return false;
    }
    //如果上述都满足,那么就继续判断下一个左右子节点是否相同
    return isSymmetricChild(leftTree.left,rightTree.right) && isSymmetricChild(leftTree.right,rightTree.left);
}

2.6二叉树的构建及遍历。

 思路:遍历这个字符串,根据前序遍历的方式创建二叉树,最后通过中序遍历输出结果

import java.util.Scanner;

class treeNode{
    public char val;
    public treeNode left;
    public treeNode right;
    
    public treeNode(char val){
        this.val = val;
    }
}


// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {

    public static int i;

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNextLine()) { // 注意 while 处理多个 case
            String str = in.nextLine();
            treeNode root = createNode(str);
            inOrder(root);

        }
    }
    public static treeNode createNode(String str){
        //.1遍历字符串str
        treeNode root = null;

        if (str.charAt(i) != '#'){
            //2.根据前序遍历创建二叉树
            root = new treeNode(str.charAt(i));
            i++;
            root.left = createNode(str);
            root.right = createNode(str);
        }else{
            i++;
        }
        //3.最后返回根结点
        return root;
    }

    public static void inOrder(treeNode root){
        if (root == null){
            return ;
        }
        inOrder(root.left);
        System.out.print(root.val + " ");
        inOrder(root.right);
    }
}

 2.7二叉树的分层遍历 。

public List<List<Character>> levelOrder2(TreeNode root) {
    List<List<Character>> ret = new ArrayList<>();
    if(root == null){
        return ret;
    }
    Queue<TreeNode> queue = new LinkedList<>();
    queue.offer(root);
    while (!queue.isEmpty()) {
        //得到当前队列有多大
        //通过记录每次当前队列的size数,来统计每一层的list有多少个元素,从queue中出同样的多数量的元素到list中即可
        int size = queue.size();
        List<Character> tmp = new ArrayList<>();
        while (size != 0) {
            //打印输出queue里的值
            TreeNode cur = queue.poll();
            tmp.add(cur.val);
            size--;
            if (cur.left != null) {
                queue.offer(cur.left);
            }
            if (cur.right != null) {
                queue.offer(cur.right);
            }
        }

        ret.add(tmp);
    }
    return ret;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值