数据结构之二叉树及面试题讲解(二)

简介: 数据结构之二叉树及面试题讲解

数据结构之二叉树及面试题讲解(一)+https://developer.aliyun.com/article/1413553

3,后序遍历

public void postOrder(TreeNode root) {
// 空树 直接返回
        if(root == null) return;
        postOrder(root.lChild);
        postOrder(root.rChild);
        System.out.print(root.val+" ");
    }

https://leetcode.cn/problems/binary-tree-preorder-traversal/submissions/

代码实现

public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        if(root == null) return list;
        // 遍历左子树
        List<Integer> leftTree = postorderTraversal(root.left);
        list.addAll(leftTree);
        // 遍历右子树
        List<Integer> rightTree = postorderTraversal(root.right);
        list.addAll(rightTree);
        list.add(root.val);
        return list;
    }

4.层序遍历

 使用队列来模拟实现(自己画图想一下,很简单)

/**
     * 层序遍历  一层一层的遍历  打印
     * 先遇到  先打印  fifo  先进先出  使用队列存储遍历的结点
     * @param root
     */
    // 层序遍历
    public void levelOrder(TreeNode root) {
        if(root == null) return;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while(!queue.isEmpty()) {
            TreeNode cur = queue.poll();
            System.out.print(cur.val+" ");
            if (cur.lChild != null) {
                queue.offer(cur.lChild);
            }
            if (cur.rChild != null) {
                queue.offer(cur.rChild);
            }
        }
    }

https://leetcode.cn/problems/binary-tree-level-order-traversal/submissions/

public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> ret = new ArrayList<>();
        if(root == null) return ret;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while(!queue.isEmpty()) {
            List<Integer> tmpList = new ArrayList<>();
            // 记录当前队列中的结点个数  决定了当前层的tmpList存储的结点个数  也方便添加后序的孩子节点
            int size = queue.size();
            while(size > 0) {
                TreeNode cur = queue.poll();
                if(cur.left != null) queue.offer(cur.left);
                if(cur.right != null) queue.offer(cur.right);
                tmpList.add(cur.val);
                size--;
            }
            ret.add(tmpList);
        }
        return ret;
    }

3.二叉树的基本操作

5.求结点个数  

 最基本的思路就是定义一个计数器,遍历每一个结点,遍历的方法可以是前序,中序,后序,层序,下面实现两种:递归实现和子问题思路

注:这里的递归实现采用了前序遍历的方式

/**
     * 求size  遍历每一个结点 设置一个计数器
     */
    public int size = 0;
    public int getSize(TreeNode root) {
// 空树 直接返回  结点数为1
        if(root == null) return 0;
        size++;
        getSize(root.lChild);
        getSize(root.rChild);
        return size;
    }
    // 子问题思路:结点的个数 == 左子树的节点个数+右子树的结点个数+根节点
    public int getSize2(TreeNode root) {
        if(root == null) return 0;
        return getSize2(root.lChild) +
                getSize2(root.rChild) + 1;
    }

6.求叶子节点的个数

 叶子节点即左右孩子都为空的结点,要求叶子节点的个数,需要遍历寻找;

/**
     * 求叶子节点的个数
     * 1.遍历实现  满足左右节点都为空  ++
     * 2.子问题思路:root叶子节点的个数 == 左子树叶子节点的个数+右子树叶子节点的个数
     */
    public int leafSize = 0;
    public int getLeafSize(TreeNode root) {
        // 递归结束条件  这其实是二叉树的一种情况
        // 二叉树有两类  空树  和非空树
        // 空树 没有叶子结点  返回0
        if(root == null) return 0;
        if (root.lChild == null && root.rChild == null) {
            leafSize++;
        }
        getLeafSize(root.lChild);
        getLeafSize(root.rChild);
        return leafSize;
    }
    public int getLeafSize2(TreeNode root) {
        // 子问题思路
        // root叶子节点的个数 == 左子树叶子节点的个数+右子树叶子节点的个数
        if(root == null) return 0;
        if(root.lChild == null && root.rChild == null) return 1;
        return getLeafSize2(root.lChild) + getLeafSize2(root.rChild);
    }

7.求第k层的结点个数

 转化为子问题思路

/**
     * 获取第k层结点的个数
     * 子问题思路:等价于左树第k-1层和右树第k-1层结点的个数
     * 一直走到第k层
     * @param root
     * @param k
     * @return
     */
    public int getKLevelNodeConut(TreeNode root,int k) {
        if(root == null) return 0;
        // 等于1  证明走到了第k层  现在就是第k层的某一个节点
        if(k == 1) return 1;
        return getKLevelNodeConut(root.lChild,k-1) +
                getKLevelNodeConut(root.rChild,k-1);
    }

8.求树的高度

子问题思路:树的高度 = 左树和右树高度的最大值+1

// 这种方法可以通过  递归只计算了一次
    public int getHeight(TreeNode root) {
        // 想好递归条件  最后一定是走到null结点  其高度为0  往回归
        if(root == null) return 0;
        int leftHeight = getHeight(root.lChild);
        int rightHeight = getHeight(root.rChild);
        return leftHeight > rightHeight ? leftHeight+1 : rightHeight+1;
    }

9.判断是否包含某节点

 先判断根节点  再去遍历左子树  左子树包含 直接返回  不包含   遍历右子树

/**
     * 判断是否含有某个值的结点
     */
    public boolean find(TreeNode root,char val) {
        // 为空  直接返回
        if(root == null) return false;
        if(root.val == val) return true;
        // 遍历左子树  如果找到,则flg1为true  直接返回即可  不需要再去遍历右子树
        boolean flg1 = find(root.lChild,val);
        if(flg1) return true;
        // 遍历右子树
        boolean flg2 = find(root.rChild,val);
        if(flg2) return true;
        return false;
    }

10.判断是否是完全二叉树

 利用层序遍历的思路,把当前结点的所有孩子结点都加入(如果孩子节点是null也会被插入),当遇到null时,如果是完全二叉树,则此结点一定是最后一个节点,即queue.size == 0,如果不是完全二叉树,则queue.size != 0

/**
     * 判断是否是完全二叉树
     * 层序遍历的思路  把所有结点的左右孩子节点都存入到queue中  如果遇到null 去判断是否还存在元素
     * 存在 -- 不是完全二叉树
     * @param root
     * @return
     */
    public boolean iscompleteTree(TreeNode root) {
        if(root == null) return true;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            TreeNode cur = queue.poll();
            // 如果queue中存储的是null 它会被存储到queue中  但却不算有效数据个数
            if (cur == null) {
                if(queue.size() != 0) {
                    return false;
                }
            }
            queue.offer(cur.lChild);
            queue.offer(cur.rChild);
        }
        return true;
    }

三.二叉树的相关OJ题目

 二叉树作为面试中常考的题目有一定的难度(且难度不小),需要认真去练习,总结

1.判断两棵树是否相同

https://leetcode.cn/problems/same-tree/submissions/

思路分析:

 这题可以采用子问题思路  先分析判断的思路,先判断结构上是否一致,如果一致,再去判断值是否相同

  • 如果一个为空,一个不为空,结构上不同  返回false
  • 如果两个都为空  返回true
  • 如果结构上完全相同,去判断值是否相同

代码实现

// 先判断当前所在根是否相同  不同  判断左结点  再判断右节点
        // 不同  值不同  一个为空,一个不为空  
        // 相同  值相同  或者两个都为空
        // 一个为空,一个不为空  
        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.另一棵树的子树

 https://leetcode.cn/problems/subtree-of-another-tree/description/

思路分析

  • 先判断root是否是null,为空直接返回false
  • 判断当前根节点是否和subRoot是否是相同的树
  • 再去递归遍历root的左树和右数是否和subRoot是相同的树

代码实现

class Solution {
    private 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);
    }
    public boolean isSubtree(TreeNode root, TreeNode subRoot) {
        if(root == null ) return false;
        // 判断当前节点是否满足条件
        if(isSameTree(root,subRoot)) return true;
        // 递归遍历左树和右树
        if(isSubtree(root.left,subRoot)) return true;
        if(isSubtree(root.right,subRoot)) return true;
        // 走到这里 说明以上情况都不满足 直接返回false;
        return false;
    }
}

数据结构之二叉树及面试题讲解(三)+https://developer.aliyun.com/article/1413556

目录
相关文章
|
27天前
|
算法
【算法与数据结构】二叉树(前中后)序遍历2
【算法与数据结构】二叉树(前中后)序遍历
|
1天前
|
算法 Java
数据结构奇妙旅程之二叉树题型解法总结
数据结构奇妙旅程之二叉树题型解法总结
|
12天前
二叉树和数据结构
二叉树和数据结构
18 0
|
13天前
|
算法 API DataX
二叉树(下)+Leetcode每日一题——“数据结构与算法”“对称二叉树”“另一棵树的子树”“二叉树的前中后序遍历”
二叉树(下)+Leetcode每日一题——“数据结构与算法”“对称二叉树”“另一棵树的子树”“二叉树的前中后序遍历”
|
13天前
|
算法 DataX
二叉树(中)+Leetcode每日一题——“数据结构与算法”“剑指Offer55-I. 二叉树的深度”“100.相同的树”“965.单值二叉树”
二叉树(中)+Leetcode每日一题——“数据结构与算法”“剑指Offer55-I. 二叉树的深度”“100.相同的树”“965.单值二叉树”
|
14天前
|
算法 搜索推荐 Python
数据结构与算法在Python面试中的应用实例
【4月更文挑战第13天】本文聚焦Python面试中的数据结构与算法问题,包括排序算法、链表操作和树图遍历。重点讨论了快速排序、链表反转和二叉树前序遍历的实现,并指出理解算法原理、处理边界条件及递归操作是避免错误的关键。通过实例代码和技巧分享,帮助面试者提升面试表现。
13 0
|
20天前
|
存储 分布式数据库 数据库管理
数据结构入门 — 二叉树的概念、性质及结构
数据结构入门 — 二叉树的概念、性质及结构
11 0
|
21天前
|
机器学习/深度学习 C++
初阶数据结构之---二叉树链式结构(二叉树的构建,二叉树的前序,中序,后序和层序遍历,计算二叉树结点个数,第k层结点个数,叶子结点个数,判断是否为完全二叉树)
初阶数据结构之---二叉树链式结构(二叉树的构建,二叉树的前序,中序,后序和层序遍历,计算二叉树结点个数,第k层结点个数,叶子结点个数,判断是否为完全二叉树)
|
23天前
|
算法 索引
【算法与数据结构】深入二叉树实现超详解(全源码优化)
【算法与数据结构】深入二叉树实现超详解(全源码优化)
|
23天前
|
存储 算法
【算法与数据结构】深入解析二叉树(二)之堆结构实现
【算法与数据结构】深入解析二叉树(二)之堆结构实现