day15 二叉树part2

前置知识:int max = Integer.MIN_VALUE; 初始化最大值为最小的整数

102. 二叉树的层序遍历

中等
给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。

难点:深度优先看栈,广度优先看队列

这个题只要一想通其实就很简单了,无论你这个二叉树有多么庞大和繁杂,归根到底根节点只有一个,第二层最多两个结点,我们先将根节点加入队列。当循环不为空的时候,记录当前队列大小size,循环size次,队列依次弹出节点,并访问弹出节点的左右子树,依次将左右子树加入队列,记录当前队列大小size,循环size次,队列依次弹出节点,并访问弹出节点的左右子树……注意,并不是说,队列里只有一层的节点(应该是有两层),队列里可能同时放着第一层节点和第二层节点,我们是依靠size的大小来记住哪些节点是哪一层的。

// 迭代解法
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> res = new LinkedList<>();
        if (root == null) {
            return res;
        }
        Queue<TreeNode> q = new LinkedList<>();
        q.offer(root);
        // while 循环控制从上向下一层层遍历
        while(!q.isEmpty()){
            int size = q.size();
            TreeNode curNode;
            List<Integer> temp = new LinkedList<>(); //用来记录该层的节点值
            // for 循环控制每一层从左向右遍历
            for (int i = 0; i < size; i++) {
                curNode = q.poll();   
                temp.add(curNode.val);
                // 不断地把该层的不为空的孩子结点加入队列
                if(curNode.left != null) q.offer(curNode.left);
                if(curNode.right != null) q.offer(curNode.right);
            }
            res.add(temp);
        }
        return res;
    }
}
 // DFS 递归方式的解法
class Solution {
    List<List<Integer>> res = new LinkedList<>(); // 最终结果存在这里

    public List<List<Integer>> levelOrder(TreeNode root) {
        checkFun(root, 0);
        return res;
    }
    public void checkFun(TreeNode node, int deep){
        // 传进来的节点为空,直接返回
        if (node == null) return; 
        // 传进来的节点不为空,继续操作
        deep++; //既然该层节点不为空,那么层数就应该加一

        // 如果结果链表的深度比当前deep还小,那么就给它加一层
        if (res.size() < deep){
            
            List<Integer> level = new LinkedList<>();
            res.add(level);
        }
        // 利用list的索引值进行层级界定
        // deep其实和res.size()是一样的,但是索引是从0开始的,所以要减一
        res.get(deep - 1).add(node.val); 

        checkFun(node.left, deep);
        checkFun(node.right, deep);
    }

}

以下题目为黑体的几题都可以用上述代码改一下秒了:
107. 二叉树的层序遍历 II
中等
给你二叉树的根节点 root ,返回其节点值 自底向上的层序遍历 。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历

class Solution {
    public List<List<Integer>> levelOrderBottom(TreeNode root) {
        List<List<Integer>> res = new LinkedList<>();
        if (root == null) {
            return res;
        }
        Queue<TreeNode> q = new LinkedList<>();
        q.offer(root);
        // while 循环控制从上向下一层层遍历
        while(!q.isEmpty()){
            int size = q.size();
            TreeNode curNode;
            List<Integer> temp = new LinkedList<>(); //用来记录该层的节点值
            // for 循环控制每一层从左向右遍历
            for (int i = 0; i < size; i++) {
                curNode = q.poll();   
                temp.add(curNode.val);
                // 不断地把该层的不为空的孩子结点加入队列
                if(curNode.left != null) q.offer(curNode.left);
                if(curNode.right != null) q.offer(curNode.right);
            }
            // 新遍历到的层插到头部, 这样就满足按照层次反序的要求
            res.addFirst(temp);
        }
        return res;
    }
}

199. 二叉树的右视图
中等
给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。

class Solution {
    public List<Integer> rightSideView(TreeNode root) {
        List<Integer> res = new LinkedList<>();
        if (root == null) {
            return res;
        }
        Queue<TreeNode> q = new LinkedList<>();
        q.offer(root);
        // while 循环控制从上向下一层层遍历
        while(!q.isEmpty()){
            int size = q.size();
            TreeNode curNode;
            // for 循环控制每一层从左向右遍历
            for (int i = 0; i < size; i++) {
                curNode = q.poll();   
                if (i == size - 1)  res.add(curNode.val);// 记录这一层的最右边的数
                // 不断地把该层的不为空的孩子结点加入队列
                if(curNode.left != null) q.offer(curNode.left);
                if(curNode.right != null) q.offer(curNode.right);
            }
        }
        return res;
    }
}

637. 二叉树的层平均值
简单
给定一个非空二叉树的根节点 root , 以数组的形式返回每一层节点的平均值。与实际答案相差 10-5 以内的答案可以被接受

class Solution {
    public List<Double> averageOfLevels(TreeNode root) {
        List<Double> res = new LinkedList<>();
        if (root == null) {
            return res;
        }
        Queue<TreeNode> q = new LinkedList<>();
        q.offer(root);
        // while 循环控制从上向下一层层遍历
        while(!q.isEmpty()){
            int size = q.size();
            TreeNode curNode;
            double sum = 0; //用来记录该层的节点和,记住是double类型!!
            // for 循环控制每一层从左向右遍历
            for (int i = 0; i < size; i++) {
                curNode = q.poll();   
                sum += curNode.val;// 记录节点值
                // 不断地把该层的不为空的孩子结点加入队列
                if(curNode.left != null) q.offer(curNode.left);
                if(curNode.right != null) q.offer(curNode.right);
            }
            res.add(sum / size);
        }
        return res;
    }
}

429. N 叉树的层序遍历
中等
给定一个 N 叉树,返回其节点值的层序遍历。(即从左到右,逐层遍历)。
树的序列化输入是用层序遍历,每组子节点都由 null 值分隔(参见示例)。

class Solution {
    public List<List<Integer>> levelOrder(Node root) {
        List<List<Integer>> res = new LinkedList<>();
        if (root == null) {
            return res;
        }
        Queue<Node> q = new LinkedList<>();
        q.offer(root);
        // while 循环控制从上向下一层层遍历
        while(!q.isEmpty()){
            int size = q.size();
            Node curNode;
            List<Integer> temp = new LinkedList<>(); //用来记录该层的节点值
            // for 循环控制每一层从左向右遍历
            for (int i = 0; i < size; i++) {
                curNode = q.poll();   
                temp.add(curNode.val);

                // 不断地把该层的不为空的孩子结点加入队列
                List<Node> kids = curNode.children;
                if (kids != null){ // 可以不加这行
                    for (Node kid : kids){
                        if (kid != null) q.offer(kid);
                    }
                }

            }
            res.add(temp);
        }
        return res;
    }
}

515. 在每个树行中找最大值
中等
给定一棵二叉树的根节点 root ,请找出该二叉树中每一层的最大值

class Solution {
    public List<Integer> largestValues(TreeNode root) {
        List<Integer> res = new LinkedList<>();
        if (root == null) {
            return res;
        }
        Queue<TreeNode> q = new LinkedList<>();
        q.offer(root);
        // while 循环控制从上向下一层层遍历
        while(!q.isEmpty()){
            int size = q.size();
            TreeNode curNode;
            int levelMax = Integer.MIN_VALUE;    //用来记录该层的最大节点值
            // for 循环控制每一层从左向右遍历
            for (int i = 0; i < size; i++) {
                curNode = q.poll();   
                levelMax = levelMax > curNode.val ? levelMax : curNode.val; 
                
                // 不断地把该层的不为空的孩子结点加入队列
                if(curNode.left != null) q.offer(curNode.left);
                if(curNode.right != null) q.offer(curNode.right);
            }
            res.add(levelMax);
        }
        return res;
    }
}

116. 填充每个节点的下一个右侧节点指针
中等
给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。
初始状态下,所有 next 指针都被设置为 NULL

class Solution {
    public Node connect(Node root) {
        if (root == null) {
            return root;
        }
        Queue<Node> q = new LinkedList<>();
        q.offer(root);
        // while 循环控制从上向下一层层遍历
        while(!q.isEmpty()){
            int size = q.size();
            Node curNode;
           
            // for 循环控制每一层从左向右, 让他们的指针指向右方
            for (int i = 0; i < size; i++) {
                curNode = q.poll();
                if (i == size - 1) {
                    curNode.next = null;
                } else {
                    curNode.next = q.peek();
                }

                // 不断地把该层的不为空的孩子结点加入队列
                if(curNode.left != null) q.offer(curNode.left);
                if(curNode.right != null) q.offer(curNode.right);
            }
        }

        return root;
    }
}

117. 填充每个节点的下一个右侧节点指针 II
中等
给定一个二叉树:
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL 。
初始状态下,所有 next 指针都被设置为 NULL

class Solution {
    public Node connect(Node root) {
        if (root == null) {
            return root;
        }
        Queue<Node> q = new LinkedList<>();
        q.offer(root);

        while (!q.isEmpty()){
            Node cur;
            int sz = q.size();

            for (int i = 0; i < sz; i++){
                cur = q.poll();

                if (i == sz - 1){
                    cur.next = null;
                } else {
                    cur.next = q.peek();
                }
                if (cur.left != null) q.offer(cur.left);
                if (cur.right != null) q.offer(cur.right);
            }
        }
        return root;
    }
}

226. 翻转二叉树

简单
给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点
day15 二叉树part2_第1张图片

 // 前序递归遍历翻转
class Solution {
    /**
     * 前后序遍历都可以
     * 中序不行,因为先左孩子交换孩子,再根交换孩子(做完后,右孩子已经变成了原来的左孩子),再右孩子交换孩子(此时其实是对原来的左孩子做交换)
     */
    public TreeNode invertTree(TreeNode root) {
        preOrder(root);
        return root;
    }
    public void preOrder(TreeNode node){
        if (node == null) {
            return;
        }
        TreeNode temp;
        // 翻转节点
        temp = node.left;
        node.left = node.right;
        node.right = temp;
        // 上面的4行代码处理了当前节点,下面两行的处理左右节点,所以是前序遍历,如果上下交换那就是后序遍历了
        preOrder(node.left);
        preOrder(node.right);
    }

101. 对称二叉树

简单
给你一个二叉树的根节点 root , 检查它是否轴对称。

class Solution {
    public boolean isSymmetric(TreeNode root) {
        // 检查二叉树是否对称,最关键的点是,将这个树从根节点劈开,形成两个分别以根节点的左右节点为根节点的子树,然后采用遍历的方法,检查两棵子树是否一致
        return compare(root.left, root.right);
    }
    // 其实这个递归的函数,每次只能比较一对轴对称的节点
    public boolean compare(TreeNode left, TreeNode right){
        //递归的终止条件是两个节点都为空
		//或者两个节点中有一个为空
		//或者两个节点的值不相等
        if (left == null && right == null) {
            return true;
        }
        if (left == null && right != null) {
            return false;
        }
        if (left != null && right == null) {
            return false;
        }
        if (left.val != right.val) {
            return false;
        }
        // 上面这两个节点比较完毕了,继续比较他们的左右节点是否一致
        boolean boolOutside = compare(left.left, right.right); //比较外侧
        boolean boolInside = compare(left.right, right.left); //比较外侧

        return boolInside && boolOutside; //只有内侧外侧都一致,才能返回true
    }
}

你可能感兴趣的:(java,leetcode,数据结构,算法)