java实现二叉树的遍历与构造以及三个简单问题

剑指 Offer 26. 树的子结构

题目描述

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

B是A的子结构, 即 A中有出现和B相同的结构和节点值。

例如:

给定的树 A:

     3
    / \
   4   5
  / \
 1   2

给定的树 B:

 4 
/ 
1

返回 true,因为 B 与 A 的一个子树拥有相同的结构和节点值。

递归实现

 /**
     * @description 剑指 Offer 26. 树的子结构 
     * @author HelloWorld
     * @create 2023/7/23 06:56
     * @param A
     * @param B
     * @return boolean
     */
    public boolean isSubStructure(TreeNode A, TreeNode B) {
        boolean result = false;
        if (null == A || null == B) {
            return result;
        }

        return compare(A, B) || isSubStructure(A.left, B) || isSubStructure(A.right, B);
    }

    private boolean compare(TreeNode A, TreeNode B) {
        if (null == B) {
            return true;
        }
        if (null == A) {
            return false;
        }

        if (A.val != B.val) {
            return false;
        }

        return compare(A.left, B.left) && compare(A.right, B.right);
    }

非递归实现

 /**
     * @description 剑指 Offer 26. 树的子结构 非递归实现
     * @author HelloWorld
     * @create 2023/7/23 10:21
     * @param A
     * @param B
     * @return boolean
     */
    public boolean isSubStructureIter(TreeNode A, TreeNode B) {
        if (null == A || null == B) {
            return false;
        }

        Stack<TreeNode> stack = new Stack<>();
        stack.push(A);
        while (!stack.isEmpty()) {
            TreeNode treeNode = stack.pop();
            if (treeNode.val == B.val && compareIter(treeNode, B)) {
                return true;
            }

            addIfNotNull(stack, treeNode.right);
            addIfNotNull(stack, treeNode.left);
        }

        return false;
    }

    private boolean compareIter(TreeNode A, TreeNode B) {
        Stack<TreeNode> stackA = new Stack<>();
        Stack<TreeNode> stackB = new Stack<>();
        stackA.push(A);
        stackB.push(B);

        while (!stackA.isEmpty() && !stackB.isEmpty()) {
            TreeNode treeNodeA = stackA.pop();
            TreeNode treeNodeB = stackB.pop();

            if (null == treeNodeB) {
                continue;
            }

            if (null == treeNodeA || treeNodeA.val != treeNodeB.val) {
                return false;
            }

            stackA.push(treeNodeA.left);
            stackA.push(treeNodeA.right);

            stackB.push(treeNodeB.left);
            stackB.push(treeNodeB.right);
        }

        return true;
    }


    private void addIfNotNull(Collection<TreeNode> collection, TreeNode treeNode) {
        if (null != treeNode) {
            collection.add(treeNode);
        }
    }

剑指 Offer 27. 二叉树的镜像

题目描述

请完成一个函数,输入一个二叉树,该函数输出它的镜像。

例如输入:

       4
      / \ 
     2   7
    / \ / \
   1  3 6  9

镜像输出:

    4 
   / \ 
  7   2
 / \ / \
9  6 3  1

垃圾的思路

先获取镜像后的遍历结果,再去构建二叉树

/**
     * @description 二叉树的镜像
     * @author HelloWorld
     * @create 2023/7/23 10:26
     * @param root
     * @return com.wy.leetcode.practise_30.TreeNode
     *
     */
    public TreeNode mirrorTree(TreeNode root) {
        if (null == root) {
            return root;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);

        List<Integer> result = new ArrayList<>();
        while (!queue.isEmpty()) {
            int size = queue.size();
            LinkedList<Integer> list = new LinkedList<>();
            for (int i = 0; i < size; i++) {
                TreeNode treeNode = queue.poll();
                if (null != treeNode) {
                    list.addFirst(treeNode.val);
                    queue.add(treeNode.left);
                    queue.add(treeNode.right);
                } else {
                    list.addFirst(null);
                }
            }

            result.addAll(list);
        }

        return initTree(result);
    }

    private TreeNode initTree(List<Integer> list) {
        TreeNode root = new TreeNode(list.get(0));
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);

        int i = 1;
        while (!queue.isEmpty() && i < list.size()) {
            TreeNode treeNode = queue.poll();
            if (null != list.get(i)) {
                treeNode.left = new TreeNode(list.get(i));
                queue.add(treeNode.left);
            }
            i++;

            if (i < list.size() && null != list.get(i)) {
                treeNode.right = new TreeNode(list.get(i));
                queue.add(treeNode.right);
            }
            i++;
        }

        return root;
    }

站在大神的肩膀上

/**
     * @description 二叉树的镜像
     * @author HelloWorld
     * @create 2023/7/23 10:26
     * @param root
     * @return com.wy.leetcode.practise_30.TreeNode
     *
     *  本质是交换每一层级的左右节点
     */
    public TreeNode mirrorTree(TreeNode root) {
        if (null == root) {
            return root;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);

        while (!queue.isEmpty()) {
            int size = queue.size();
            LinkedList<Integer> list = new LinkedList<>();
            for (int i = 0; i < size; i++) {
                TreeNode treeNode = queue.poll();
                // 交换左右节点
                TreeNode temp = treeNode.left;
                treeNode.left = treeNode.right;
                treeNode.right = temp;

                if (null != treeNode.left) { queue.offer(treeNode.left);}
                if (null != treeNode.right) { queue.offer(treeNode.right);}
            }
        }

        return root;
    }

剑指 Offer 28. 对称的二叉树

请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。

例如,二叉树 [1,2,2,3,4,4,3] 是对称的。

    1
   / \
  2   2
 / \ / \
3  4 4  3

但是下面这个[1,2,2,null,3,null,3] 则不是镜像对称的:

    1
   / \
   2  2
    \  \
     3  3
/**
     * @description 剑指 Offer 28. 对称的二叉树
     * @author HelloWorld
     * @create 2023/7/23 14:28
     * @param root
     * @return boolean
     */
    public boolean isSymmetric(TreeNode root) {
        if (root == null) {
            return true;
        }

        Queue<TreeNode> queueA = new LinkedList<>();
        Queue<TreeNode> queueB = new LinkedList<>();

        queueA.offer(root.left);
        queueB.offer(root.right);

        while (!queueA.isEmpty() && !queueB.isEmpty()) {
            int size = queueA.size();

            if (size != queueB.size()) {
                return false;
            }

            for (int i = 0; i < size; i++) {
                TreeNode treeNodeA = queueA.poll();
                TreeNode treeNodeB = queueB.poll();
                if (treeNodeB == null && treeNodeA == null) {
                    continue;
                }

                if (treeNodeB == null || treeNodeA == null || treeNodeA.val != treeNodeB.val) {
                    return false;
                }

                queueA.offer(treeNodeA.left);
                queueA.offer(treeNodeA.right);

                queueB.offer(treeNodeB.right);
                queueB.offer(treeNodeB.left);
            }
        }

        return queueA.isEmpty() && queueB.isEmpty();
    }

二叉树的遍历与构造

package com.wy.leetcode.practise_30;

import java.util.*;

/**
 * @author yuyang.zhang
 * @Description
 * @date 2023/7/21
 */
public class TreeNode {
    public int val;
    public TreeNode left;

    public TreeNode right;

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



    /**
     * @description 根据层次遍历的结果还原二叉树
     *  层次遍历结果:3,9,20,null,null,15,7
     *     3
     *    / \
     *   9  20
     *     /  \
     *    15   7
     * @author HelloWorld
     * @create 2023/7/22 09:16
     * @param values
     * @return com.wy.leetcode.practise_30.TreeNode
     */
    public static TreeNode init(Integer ...values) {
        TreeNode root = new TreeNode(values[0]);

        Queue<TreeNode> treeNodeQueue = new LinkedList<>();
        treeNodeQueue.add(root);

        int i = 1;
        while (!treeNodeQueue.isEmpty() && i < values.length) {
            TreeNode treeNode = treeNodeQueue.poll();
            // 左孩子是否存在
            if (values[i] != null) {
                treeNode.left = new TreeNode(values[i]);
                treeNodeQueue.add(treeNode.left);
            }
            i++;

            if (i < values.length && values[i] != null) {
                treeNode.right = new TreeNode(values[i]);
                treeNodeQueue.add(treeNode.right);
            }

            i++;
        }

        return root;
    }


    /**
     * @description 层次遍历
     * @author HelloWorld
     * @create 2023/7/23 08:56
     * @param root
     * @return java.util.List<java.lang.Integer>
     */
    public static List<Integer> levelOrderTraversal(TreeNode root) {
        List<Integer> result = new ArrayList<>();
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        while (!queue.isEmpty()) {
            TreeNode treeNode = queue.poll();
            result.add(treeNode.val);

            addIfNotNull(queue, treeNode.left);
            addIfNotNull(queue, treeNode.right);
        }

        return result;
    }

    /**
     * @description 前序遍历:根,左,右
     * @author HelloWorld
     * @create 2023/7/23 08:58
     * @param root
     * @return void
     */
    public static List<Integer> preOrderTraversal(TreeNode root) {
        List<Integer> result = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode node = stack.pop();
            result.add(node.val);
            addIfNotNull(stack, node.right);
            addIfNotNull(stack, node.left);
        }

        return result;
    }

    /**
     * @description 中序遍历 左根右
     * @author HelloWorld
     * @create 2023/7/23 09:20
     * @param root
     * @return java.util.List<java.lang.Integer>
     */
    public static List<Integer> inOrderTraversal(TreeNode root) {
        List<Integer> result = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        TreeNode node = root;
        while (null != node || !stack.isEmpty()) {
            while (null != node) {
                stack.push(node);
                node = node.left;
            }

            node= stack.pop();
            result.add(node.val);
            node = node.right;
        }

        return result;
    }

    /**
     * @description 后续遍历
     * @author HelloWorld 左右根
     * @create 2023/7/23 09:09
     * @param node
     * @return java.util.List<java.lang.Integer>
     */
    public static List<Integer> postOrderTraversal(TreeNode node) {
        Stack<TreeNode> resultStack = new Stack<>();
        Stack<TreeNode> stack = new Stack<>();
        stack.add(node);
        while (!stack.isEmpty()) {
            TreeNode treeNode = stack.pop();
            resultStack.push(treeNode);

            addIfNotNull(stack, treeNode.left);
            addIfNotNull(stack, treeNode.right);
        }

        List<Integer> result = new ArrayList<>();
        while (!resultStack.isEmpty()) {
            result.add(resultStack.pop().val);
        }

        return result;
    }


    private static void addIfNotNull(Collection<TreeNode> collection, TreeNode node) {
        if (null != node) {
            collection.add(node);
        }
    }

    public static void main(String[] args) {
        TreeNode node = init(1, 2, 3, 4, 5, 6, 7, 8, 9);
        List<Integer> integers = levelOrderTraversal(node);
        for (Integer integer : integers) {
            System.out.println(integer);
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值