「刷题」二叉树的题刷不动?快进来拓展解题思路!

个人主页:Ice_Sugar_7
所属专栏:数据结构刷题
欢迎点赞收藏加关注哦!

题单

  • 对称二叉树
  • 层序遍历二叉树
  • 由前序、中序遍历构造二叉树

对称二叉树

题目链接

思路:现在有两个节点root1、root2,它们有共同的根节点,如果root1的左子树、右子树分别和root2的右子树、左子树相同,那就是对称的
需要注意的是,题干给的方法只有一个参数root,但是我们要两边同时走,也就需要两个参数,所以需要额外写一个方法

    public boolean isSymmetric(TreeNode root) {
        if(root == null) {
            return true;
        }
        return Symmetric(root.left,root.right);
    }

    public boolean Symmetric(TreeNode root1,TreeNode root2) {
        //整体思路是前序遍历,先对根节点进行判断
        if(root1 == null && root2 == null) {
            return true;
        }
        //到这里,root1和root2至少有一个不为空,接下来判断有没有一个是空的,若有,那就不是对称的了
        if(root1 == null || root2 == null) {
            return false;
        }
        //到这里,root1和root2都不为空
        //比较根节点的值
        if(root1.val != root2.val) {
            return false;
        } else {
            //从else开始就是遍历根节点的左子树和右子树
            boolean ret1 = Symmetric(root1.left,root2.right);
            boolean ret2 = Symmetric(root1.right,root2.left);
            if(ret1 && ret2) {
                return true;
            } else {
                return false;
            }
        }
    }


层序遍历二叉树

题目链接

思路:用队列存储二叉树每一层的元素,定义一个变量size记录入队后队列的元素个数,也就是二叉树每一层的元素个数
为什么要记录呢?因为我们需要弹出这一层的节点,然后“带”出下一层的节点的,要知道弹出多少个节点

class Solution {
    Queue<TreeNode> queue = new LinkedList<>();

    public List<List<Integer>> levelOrder(TreeNode root) {
        if(root == null)
            return new ArrayList<>();
        List<List<Integer>> ret = new ArrayList<>();
        queue.offer(root);

        while(!queue.isEmpty()) {
            List<Integer> list = new ArrayList<>();
            int size = queue.size();

            //这个循环实现:将第k层的元素出队列,让第k+1层元素入队
            while(size-- > 0) {
                TreeNode top = queue.poll();  //取当前队头的元素
                list.add(top.val);  //每取出一个,就放到list里面
                if(top.left != null)
                    queue.offer(top.left);
                if(top.right != null)
                    queue.offer(top.right);
            }
            ret.add(list); //将list放进ret,相当于将一维数组放进二维数组
        }
        return ret;
    }
}

由前序、中序遍历构造二叉树

题目链接

思路:根据前序遍历推出根节点,然后找出根节点在中序遍历数组中的位置,这样就能知道剩下的节点是在左子树还是右子树
「刷题」二叉树的题刷不动?快进来拓展解题思路!_第1张图片
「刷题」二叉树的题刷不动?快进来拓展解题思路!_第2张图片
以上图为例,由中序遍历的数组可知,20在以3为根节点的右子树,而在preorder中,20是右子树部分第一个数,说明它是这个右子树的根节点
(这里解释一下原因:因为前序遍历是按照根、左、右的顺序遍历的,所以遇到的第一个节点就是根节点)

以3为根节点分割好之后,继续对左右子树进行分割:先找出子树根节点在中序数组的位置,然后分割为更小的区间

class Solution {
    public int prei; //记录遍历到前序数组的哪个下标

    public TreeNode buildTree(int[] preorder, int[] inorder) {
        return devide(preorder,inorder,0,inorder.length - 1);
    }

    //val:要找的根节点的值
    public int findIndex(int val,int[] inorder) {
        for(int i = 0;i < inorder.length;i++) {
            if(inorder[i] == val) {
                return i;  //返回它在inorder中的下标
            }
        }
        return -1;
    }
    
	//begin、end:子树的起始、终止下标
    public TreeNode devide(int[] preorder,int[] inorder,int begin,int end) {
        //当end < begin时递归结束,注意end == begin时也要进行递归,此时也要创建节点
        if(end < begin)
            return null;

        //从中序遍历数组中找到“分割点”
        int dev = findIndex(preorder[prei++],inorder);  //dev:分割点在inorder中的下标
        //分割点就是根节点
        TreeNode node = new TreeNode(inorder[dev]);
        //通过递归连接左右子树
        node.left = devide(preorder,inorder,begin,dev-1);
        node.right = devide(preorder,inorder,dev+1,end);
        return node;
    }
}

你可能感兴趣的:(数据结构刷题,java,开发语言,数据结构)