JAVA二刷-Day15 | 层序遍历*10, 226.翻转二叉树, 101.对称二叉树

JAVA二刷-Day15 | 层序遍历*10, 226.翻转二叉树, 101.对称二叉树

层序遍历

LeetCode题目:
102.二叉树的层序遍历
107.二叉树的层次遍历II
199.二叉树的右视图
637.二叉树的层平均值
429.N叉树的层序遍历
515.在每个树行中找最大值
116.填充每个节点的下一个右侧节点指针
117.填充每个节点的下一个右侧节点指针II
104.二叉树的最大深度
111.二叉树的最小深度

解题思路

  层序遍历的方法都比较类似,因为首先要对每一层的元素进行维护,因此需要用容器来进行存储,同时容器在获取元素的同时,应当将该元素节点的子节点放入容器中。如果直接用容器内部的size来判定是否取完该层节点,则会出现因为不断增加子节点无法分层。因此需要在获取子节点之前先确定容器当前的size,以此来判定是否取完了当前层的节点。

  此外,层节点要取出,应该遵循的是FIFO原则,因此要使用队列进行存储,以下是102的代码:

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        Queue<TreeNode> queTree = new LinkedList<TreeNode>();
        List<List<Integer>> result = new ArrayList<>();
        TreeNode node;
        if (root != null) queTree.offer(root);
        while (!queTree.isEmpty()) {
            int size = queTree.size();
            List<Integer> resultLevel = new ArrayList<>();
            for (int i = 0; i < size; i++) {
                node = queTree.peek();
                queTree.poll();
                if (node.left != null) queTree.offer(node.left);
                if (node.right != null) queTree.offer(node.right);
                resultLevel.add(node.val);
            }
            result.add(resultLevel);

        }

        return result;
    }
}

进阶:117.填充每个节点的下一个右侧节点指针II

LeetCode题目链接:https://leetcode.cn/problems/minimum-depth-of-binary-tree/

解题思路

  按照题目中进阶要求,使用O(1)的空间复杂度完成代码,同时不考虑递归所产生的额外函数栈空间,因此首选使用递归来完成。因此,每次递归root节点,都可以将接下来的root下的子节点的next关系进行获得。

  但存在一些问题,即递归的时候,左子树部分的next关系依赖于右子树父节点的next关系。如果递归先遍历左子树进行操作。那么会直接循环到左子树的地步,此时中间层的右子树next关系还没有构建出来。因此会造成next没有完全。

  因此需要先递归右子树,再递归左子树,代码如下:

class Solution {
    public Node getNext(Node root) {
        if (root == null) return null;
        if (root.left != null) {
            return root.left;
        }else if (root.left == null && root.right != null) {
            return root.right;
        }else {
            return getNext(root.next);
        }
    }

    public Node connect(Node root) {
        if (root == null) return root;
        if (root.left != null && root.right !=null) {
            root.left.next = root.right;
        }else if (root.left != null && root.right == null) {
            root.left.next = getNext(root.next);
        }
        if (root.right != null) {
            root.right.next = getNext(root.next);
        }

        connect(root.right);
        connect(root.left);
        

        return root;        
    }
}

翻转二叉树

LeetCode题目链接:https://leetcode.cn/problems/invert-binary-tree/

解题思路

  迭代法可以使用层序遍历的方法逐层次进行翻转。递归方法使用时候要注意中序遍历的特殊情况。

  具体代码如下:

class Solution {
    public TreeNode invertTree(TreeNode root) {
        if (root == null) return null;
        TreeNode temp = root.left;
        root.left = root.right;
        root.right = temp;
        root.left = invertTree(root.left);
        root.right = invertTree(root.right);

        return root;
    }
}

对称二叉树

LeetCode题目链接:https://leetcode.cn/problems/symmetric-tree/

解题思路

  对称二叉树在进行比较的时候,应当从最末尾处逐级返回是否匹配成功,如果一个匹配不成功false,结果应当也返回false。同时,因为要涉及左右两个分支的对比,所以应当使用递归的方法来进行逐级的比较和返回。

  在对比左右子树的节点对称时候,应当左子树的左节点与右子树的右节点对比。左子树的右节点和右子树的左节点进行对比,当两次对比均相同才能说明该层对称。因此应当使用&&进行两次对比后判定结果。同时,当子树对称,且子节点不为空时候,才有必要继续递归,所以递归的条件只有left.val==right.val的时候。

  具体代码如下:

class Solution {

    public boolean compare(TreeNode right, TreeNode left) {
        if (left == null && right != null) {
            return false;
        }else if (left != null && right == null) {
            return false;
        }else if (left == null && right == null) {
            return true;
        }else if (left.val != right.val) {
            return false;
        }

        boolean outside = compare(right.right, left.left);
        boolean inside = compare(right.left, left.right);
        return outside&&inside;
    }

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

        return compare(root.right, root.left);

    }
}

  如果使用迭代法,则需要注意将需要对比的两个元素放在邻近位置,以便于对比是否对称。同时,对比后即可弹出,因此使用队列来进行。

  代码如下:

class Solution {

    public boolean isSymmetric(TreeNode root) {
        if (root == null) return true;
        Queue<TreeNode> queTree = new LinkedList<>();
        TreeNode node = root;
        queTree.offer(root.left);
        queTree.offer(root.right);
        while (!queTree.isEmpty()) {
            TreeNode leftNode = queTree.peek();
            queTree.poll();
            TreeNode rightNode = queTree.peek();
            queTree.poll();

            if (leftNode == null && rightNode == null) {
                continue;
            }

            if (leftNode == null && rightNode != null) {
                return false;
            }else if (leftNode != null && rightNode == null) {
                return false;
            }else if (leftNode.val != rightNode.val) {
                return false;
            }

            queTree.offer(leftNode.left);
            queTree.offer(rightNode.right);
            queTree.offer(leftNode.right);
            queTree.offer(rightNode.left);
        }

        return true;

    }
}

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