整理五道算法题系列(1)二叉树相关

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Joryun/article/details/79942636

背景

最近想整理一些有意思的题目,特别是给力的破题技巧与思想,均为学习笔记,于此做个长期记录。不多说,进入算法世界了~~

说明

=> 五道 / 篇
=> Java
=> 二叉树相关

题目

1、重建二叉树

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

思路:首先得了解先序、中序的特点,接着从先序定位根,然后再去中序找出左右子树,依旧是递归实现。

public TreeNode reConstructBinaryTree(int[] pre, int[] in) {
        return reConstructBinaryTree(pre, 0, pre.length - 1,
                in, 0, in.length - 1);
    }

    /**
     * @param pre      前序
     * @param startPre 前序首位
     * @param endPre   前序末位
     * @param in       中序
     * @param startIn  中序首位
     * @param endIn    中序末位
     * @return
     */
    public TreeNode reConstructBinaryTree(int[] pre, int startPre, int endPre,
                                          int[] in, int startIn, int endIn) {
        // constraint
        if (startPre > endPre || startIn > endIn) {
            return null;
        }

        // 先序第一位即为根
        TreeNode root = new TreeNode(pre[startPre]);
        for (int i = startIn; i <= endIn; i++) {
            // 中序找寻根所在位置
            if (in[i] == pre[startPre]) {
                /*
                  重点解析
                  1. startPre + i - startIn : 根据中序所找到的根,从而得知下一次递归的左子树,接着找到
                  前序的左子树部分,再次根据前序“根左右”的特性传入startPre 和 endPre,而由于startPre每次都在向
                  右,因此endPre应该根据startPre来决定
                  2. (startPre + i - startIn) + 1 :根据中序所找到的根,从而得知下一次递归的右子树,而上一步已
                  经在前序序列中分隔出根、左子树、右子树,那基本可以确定传入的数组下标
                 */
                root.left = reConstructBinaryTree(pre, startPre + 1, startPre + i - startIn,
                        in, startIn, i - 1);
                root.right = reConstructBinaryTree(pre, (startPre + i - startIn) + 1, endPre,
                        in, i + 1, endIn);
            }
        }
        return root;
    }

    private class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;

        public TreeNode(int val) {
            this.val = val;
        }
    }

2、树的子结构

输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)

思路:土方法,一个个比较,但是递归比较,以B树为参考系,从根开始匹配。

public boolean HasSubtree(TreeNode root1, TreeNode root2) {
        boolean result = false;
        if (root2 != null && root1 != null) {
            // 如果找到了对应Tree2的根节点的点
            if (root1.val == root2.val) {
                result = doesTree1HaveTree2(root1, root2);
            }
            // 如果找不到,那么就再将root的左儿子当作起点,去判断时包含Tree2
            if (!result) {
                result = doesTree1HaveTree2(root1.left, root2);
            }
            // 如果还找不到,那么就再将root的右儿子当作起点,去判断时候包含Tree2
            if (!result) {
                result = HasSubtree(root1.right, root2);
            }
        }
        return result;
    }

    public boolean doesTree1HaveTree2(TreeNode node1, TreeNode node2) {
        /*
        node1 和 node2 的为空判断务必得记住,一开始挺容易漏掉这个约束的!
         */
        // 如果Tree2已经遍历完了都能对应得上,返回true
        if (node2 == null) {
            return true;
        }
        // 如果Tree2还没遍历完,Tree1却遍历完了。返回false
        if (node1 == null) {
            return false;
        }
        // 如果其中有一个点没有对应上,返回false
        if (node1.val != node2.val) {
            return false;
        }
        // 如果根节点对应的上,那么就分别去子节点里面匹配
        return doesTree1HaveTree2(node1.left, node2.left) && doesTree1HaveTree2(node1.right, node2.right);
    }

    private class TreeNode {
        int val = 0;
        TreeNode left = null;
        TreeNode right = null;

        public TreeNode(int val) {
            this.val = val;

        }
    }

3、镜像二叉树

操作给定的二叉树,将其变换为源二叉树的镜像。
输入描述:

思路:递归交换左右节点

public void Mirror(TreeNode root) {
        TreeNode tmp;
        if (root != null) {
            tmp = root.left;
            root.left = root.right;
            root.right = tmp;
            if (root.left != null) {
                Mirror(root.left);
            }
            if (root.right != null) {
                Mirror(root.right);
            }
        }
    }

    private class TreeNode {
        int val = 0;
        TreeNode left = null;
        TreeNode right = null;

        public TreeNode(int val) {
            this.val = val;

        }
    }

4、打印二叉树

从上往下打印出二叉树的每个节点,同层节点从左至右打印。

思路:先序的遍历打印方式,巧妙运用Queue实现,利用其“先进先出”的特点。

public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
        ArrayList<Integer> list = new ArrayList<>();
        if (root == null) {
            return list;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        /*
        while循环主要针对的是queue是否为空,而queue实际存储的是每层的根节点,因此便可每层按顺序存进list
         */
        while (!queue.isEmpty()) {
            TreeNode treeNode = queue.poll();
            if (treeNode.left != null) {
                queue.offer(treeNode.left);
            }
            if (treeNode.right != null) {
                queue.offer(treeNode.right);
            }
            list.add(treeNode.val);
        }
        return list;
    }

    private class TreeNode {
        int val = 0;
        TreeNode left = null;
        TreeNode right = null;

        public TreeNode(int val) {
            this.val = val;

        }
    }

5、二叉搜索树的后序遍历序列

输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。

扫描二维码关注公众号,回复: 3814146 查看本文章

思路:首先得了解二叉搜索树(BST),接着递归判断是否满足BST的条件。

public boolean VerifySquenceOfBST(int[] sequence) {
        if (sequence.length == 0) {
            return false;
        }
        if (sequence.length == 1) {
            return true;
        }
        return judge(sequence, 0, sequence.length - 1);
    }

    public boolean judge(int[] a, int start, int end) {
        if (start > end) {
            return true;
        }
        int i = start;
        /*
        找寻左右子树的分界点
         */
        while (a[i] < a[end]) {
            ++i;
        }
        for (int j = i; j < end; j++) {
            if (a[j] < a[end]) {
                return false;
            }
        }
        /*
        递归,分出左右子树再次递归判断
         */
        return judge(a, start, i - 1) && judge(a, i, end - 1);
    }

猜你喜欢

转载自blog.csdn.net/Joryun/article/details/79942636