找树左下角的值[(前序遍历 || 分层遍历)变体]

二叉树遍历

  • 前言
  • 一、找树左下角的值
  • 二、遍历+改进
    • 1、前序遍历
    • 2、层次遍历
  • 总结
  • 参考文献

前言

二叉树遍历有递归遍历和层次遍历,这是操作二叉树的基础。

一、找树左下角的值

找树左下角的值[(前序遍历 || 分层遍历)变体]_第1张图片

二、遍历+改进

1、前序遍历

// 找树左下角的值。
public class FindBottomLeftValue {
    /*
    target:找出二叉树最下最左边的值。
    该值特点:深度最大。
    如何拿到深度最大的节点值?通过遍历,在遍历的过程中传入深度变量,用一个变量记录最大深度那个节点值。
    当同深度有多个值时,如何拿到最左边那个值?可通过前序遍历的方式去寻找更深的节点,当深度一样时,还是保持第一次记录的节点值。
     */
    public int findBottomLeftValue(TreeNode root) {
        // 记录当前遍历过程中最左最深的节点值。
        // 初始化为根节点值,深度为1.
        int[] rs = new int[]{root.val, 1};
        // 前序遍历寻找更深的节点值。
        preOrder(root, 1, rs);
        // 返回最深最左的节点值。
        return rs[0];
    }

    /**
     * @param root  树根节点。
     * @param level 当前所在树的深度。
     * @param rs    存储最左最深的节点值和深度。
     */
    private void preOrder(TreeNode root, int level, int[] rs) {
        if (null == root) return;
        // 在前序遍历的基础上对最深最左节点进行更新。
        if (rs[1] < level) {
            rs[0] = root.val;
            // 根据前序遍历特点,能比当前记录的还深的节点,一定在下一层。
            ++rs[1];
        }
        // 先左后右。
        preOrder(root.left, level + 1, rs);
        preOrder(root.right, level + 1, rs);
    }

    // Definition for a binary tree node.
    class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;

        TreeNode() {
        }

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

        TreeNode(int val, TreeNode left, TreeNode right) {
            this.val = val;
            this.left = left;
            this.right = right;
        }
    }
}

2、层次遍历

// 练习一下层次遍历。
class FindBottomLeftValue2 {
    /*
    target:找出二叉树最下最左边的值。
    该值特点:深度最大。
    如何拿到深度最大的节点值?通过遍历,在遍历的过程中传入深度变量,用一个变量记录最大深度那个节点值。
    当同深度有多个值时,如何拿到最左边那个值?可通过层次遍历拿最后一层的第一个节点的值即可。
    如何拿最后一层的第一个节点的值?可每次记录当前层的头节点的值。
    如何分层?通过每层有多少节点数,访问一个就减一来判是否马上开启新一层的遍历。
     */
    public int findBottomLeftValue(TreeNode root) {
        // 层次遍历,按队列的出入方式来进行。
        Queue<TreeNode> que = new LinkedList<>();
        // 初始化第一层节点。
        que.add(root);
        // 记录当前层的节点个数,当前层为第一层,只有root节点。
        int curSize = 1;
        // 记录第一层的第一个节点的值。该节点为root。
        int leftNodeVal = root.val;
        // 以循环的方式开启层次遍历。
        while (!que.isEmpty()) {
            // 从左到右遍历当前层节点。
            TreeNode node = que.poll();
            // 将左右非空孩子加入层次遍历的路径中。
            if (null != node.left) que.add(node.left);
            if (null != node.right) que.add(node.right);
            // 更新当前层还剩余未遍历的节点数,并根据情况完成下一层节点数的更新和最左节点值的更新。
            if (--curSize == 0) {
                curSize = que.size();
                // 由于循环所需,que此时可能已经为空,更下一层就没有了。
                if (!que.isEmpty()) leftNodeVal = que.peek().val;
            }
        }
        // 返回最深一层的第一个节点值。
        return leftNodeVal;
    }

    // Definition for a binary tree node.
    class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;

        TreeNode() {
        }

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

        TreeNode(int val, TreeNode left, TreeNode right) {
            this.val = val;
            this.left = left;
            this.right = right;
        }
    }
}

总结

1)经典前序遍历+分层遍历。

参考文献

[1] LeetCode 找树左下角的值

你可能感兴趣的:(数据机构与算法,二叉树,前序遍历,层次遍历,Java)