leetcode-199. 二叉树的右视图

126 阅读1分钟
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

/**
 * ref:https://leetcode-cn.com/problems/binary-tree-right-side-view/
 * 给定一个二叉树的根节点root,想象自己站在它的右侧,按照从顶部到底部的顺序,
 * 返回从右侧所能看到的节点值。
 * 示例 1:
 * 输入: [1,2,3,null,5,null,4]
 * 输出: [1,3,4]
 **/
public class BinaryTreeRightSide {

    public static void main(String[] args) {
        TreeNode f22right = new TreeNode(4,null,null);
        TreeNode f21right = new TreeNode(5,null,null);
        TreeNode f1left = new TreeNode(2,null,f21right);
        TreeNode f1right = new TreeNode(3,null,f22right);
        TreeNode root = new TreeNode(1,f1left,f1right);
        System.out.println(iterateRightSideView(root));
        System.out.println(recurRightSideView(root));
    }

    /**
     * 分层迭代思想:
     * 首先将treeNode的root跟节点添加到线性表中。
     * 并设置两个变量:
     * currNum用来记录当层节点个数。
     * childNum用来记录当前层子层节点个数。
     * 然后开始迭代线性表。先迭代root层,计算出currNum和childNum数,
     * 并将当前层的左右非空子节点添加到线性表中,同时将当前层最后一个元素记录于结果集。
     * 完成一次迭代后,每层的最右侧元素就放入到结果集,并完成下一层元素个数的统计。
     * 继续完成下一层迭代,直到线性表中无元素时,结束。
     * @param root
     * @return
     */
    public static List<Integer> iterateRightSideView(TreeNode root) {
        List<Integer> result = new ArrayList<>();
        Queue<TreeNode> queue = new LinkedList();
        queue.offer(root);
        // 记录当前层节点个数
        int currNum = 1;
        // 记录当前层子节点个数
        int childNum;
        while(!queue.isEmpty()){
            // 迭代层级,取出每层最后一个元素
            childNum = 0;
            for(int i=0;i<currNum;i++){
                // 获取一个节点
                TreeNode node = queue.poll();
                // 添加每层最后一个元素
                if(currNum-i==1){
                    result.add(node.val);
                }
                // 有左侧子节点
                if(node.left!=null){
                    queue.offer(node.left);
                    childNum++;
                }

                // 有右侧子节点
                if(node.right!=null){
                    queue.offer(node.right);
                    childNum++;
                }
            }
            currNum = childNum;
        }
        return  result;
    }

    /**
     * 递归思想:
     * 首先迭代treeNode的所有右节点,当每层的右节点不为空时,加入结果集中。
     * 当节点为空时结束。每次在迭代过程中,记录当前的节点是否大于以迭代过的右节点的深度。
     * 如果超过,则将右节点(每次迭代过程中,都是采用先右厚左的方式)值记录到结果集中。
     * 主要是为了解决树不规则场景,比如左树节点深度是4,右树节点深度是3。这个时候
     * 直迭代右节点的话就会少了左树的最后一个节点。
     * @param root
     * @return
     */
    static int totalDeep = 0;
    public static List<Integer> recurRightSideView(TreeNode root) {
        List<Integer> result = new ArrayList<>();
        helper(root,result,1);
        return result;
    }

    /**
     * 迭代结束
     * @param node
     * @param result
     * @param deep
     */
    private static void helper(TreeNode node, List<Integer> result, int deep) {
        if(node==null){
            return;
        }
        if(deep>totalDeep){
            totalDeep = deep;
            result.add(node.val);
        }
        // 先右后左
        helper(node.right,result,deep+1);
        helper(node.left,result,deep+1);
    }
}