代码随想录算法训练营第15天 | 层序遍历 ,226.翻转二叉树 (优先掌握递归) ,101. 对称二叉树 (优先掌握递归)

代码随想录算法训练营第15天 | 层序遍历 ,226.翻转二叉树 (优先掌握递归) ,101. 对称二叉树 (优先掌握递归)

102.二叉树的层序遍历

  1. 因为二叉树无法遍历到一层一层 所以需要借助队列
  2. 每一层的循环时 用一个变量size去存 这一层节点的数量 这样才可以做到每一层存入一个数组
  3. 然后每次弹出一个节点时 添加这个节点的 左右节点进入队列 等到这一层全部pop掉 那么size就会重新统计下一次的元素数量
  4. 注意点 判断是否有左右节点时 要用2个if 意思为都要去判断 而不是用else if
  5. 还有 一定要用size去存下每一层的元素个数 而不是用queue.size()因为它一直会变 会加入下一层的元素
/**
 * Definition for a binary tree node.
 * public 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;
 *     }
 * }
 */
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        Deque<TreeNode> que = new LinkedList<>();
        if(root!=null){
            que.addLast(root);
        }
        List<List<Integer>> res = new ArrayList<>();
        while(!que.isEmpty()){
            int size = que.size();
            List<Integer> arr = new ArrayList<>();
            while(size--!=0){
                TreeNode node = que.pollFirst();
                arr.add(node.val);
                if(node.left!=null){
                    que.addLast(node.left);
                }
                if(node.right!=null){
                    que.addLast(node.right);
                }

                // size--;


            }
            res.add(arr);


        }
        return res;



    }
}

107.二叉树的层次遍历 II

  1. 此题需要从底向上 层序遍历二叉树 可以先从上到下遍历 然后将结果数组 反转
  2. 字符串的反转方法 为头尾双指针交换值
  3. 数组的反转方法 再新建一个数组 然后从后向前遍历原数组 添加至新数组
/**
 * Definition for a binary tree node.
 * public 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;
 *     }
 * }
 */
class Solution {
    public List<List<Integer>> levelOrderBottom(TreeNode root) {
        List<List<Integer>> res = new ArrayList<>();
        Deque<TreeNode> que = new LinkedList<>();

        if(root!=null){
            que.addLast(root);
        }

        while(!que.isEmpty()){
            int size = que.size();
            List<Integer> arr = new ArrayList<>();
            while(size--!=0){
                TreeNode node = que.pollFirst();
                arr.add(node.val);

                if(node.left!=null){
                    que.addLast(node.left);
                }

                if(node.right!=null){
                    que.addLast(node.right);
                }


            }
            res.add(arr);
        }
        List<List<Integer>> result = new ArrayList<>();
        for(int i = res.size()-1;i>=0;i--){
            result.add(res.get(i));
        }


        return result;

    }
}

199.二叉树的右视图

  1. 层序遍历的时候判断是否已经遍历到当前层的最后一个节点 如果是就加入结果数组
/**
 * Definition for a binary tree node.
 * public 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;
 *     }
 * }
 */
class Solution {
    public List<Integer> rightSideView(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        Deque<TreeNode> que = new LinkedList<>();

        if(root!=null){
            que.addLast(root);
        }


        while(!que.isEmpty()){
            int size = que.size();
            while(size--!=0){
                TreeNode node =  que.pollFirst();
                if(size==0){
                    res.add(node.val);
                }
                
                if(node.left!=null){
                    que.addLast(node.left);
                }

                if(node.right!=null){
                    que.addLast(node.right);
                }
            }
        }
        return res;

    }
}

637.二叉树的层平均值

  1. 层序遍历 每一层遍历的时候求和 然后遍历结束的时候求 平均值
/**
 * Definition for a binary tree node.
 * public 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;
 *     }
 * }
 */
class Solution {
    public List<Double> averageOfLevels(TreeNode root) {
        List<Double> res = new ArrayList<>();
        Deque<TreeNode> que = new LinkedList<>();

        if(root!=null){
            que.addLast(root);
        }



        while(!que.isEmpty()){
            int size = que.size();
            int size2 = size;
            Double sum=0.0;

            while(size--!=0){
                TreeNode node = que.pollFirst();
                
                sum+=node.val;
                if(node.left!=null){
                    que.addLast(node.left);
                }

                if(node.right!=null){
                    que.addLast(node.right);
                }



                
                    
                
            }
            Double avg = sum/size2;
            res.add(avg);
        }
        return res;
    }
}

429. N 叉树的层序遍历

  1. 一个节点可能有多个孩子 当添加节点的子节点时 去遍历子节点的数组 判断是否存在 并加入结果数组即可
  2. 定义n叉树的 构造器里面每个Node有可能有children数组 里面存他的子节点
/*
// Definition for a Node.
class Node {
    public int val;
    public List<Node> children;

    public Node() {}

    public Node(int _val) {
        val = _val;
    }

    public Node(int _val, List<Node> _children) {
        val = _val;
        children = _children;
    }
};
*/

class Solution {
    public List<List<Integer>> levelOrder(Node root) {
        List<List<Integer>> res = new ArrayList<>();
        Deque<Node> que = new LinkedList<>();

        if(root!=null){
            que.addLast(root);
        }

        while(!que.isEmpty()){
            int size = que.size();
            List<Integer> arr = new ArrayList<>();
            while(size--!=0){
                Node node = que.pollFirst();
                arr.add(node.val);

                

                //构造器里面每个Node有可能有children数组 里面存他的子节点
                for(Node child:node.children){
                    if(child!=null){
                        que.addLast(child);
                    }

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



        
    }
}

515.在每个树行中找最大值

  1. Integer.MAX_VALUE 默认的最大值 Integer.MIN_VALUE 默认的最小值
  2. 每一层遍历 比出一个最大值 赋给结果数组
/**
 * Definition for a binary tree node.
 * public 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;
 *     }
 * }
 */
class Solution {
    public List<Integer> largestValues(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        Deque<TreeNode> que = new LinkedList<>();

        if(root!=null){
            que.addLast(root);
        }

        while(!que.isEmpty()){
            int max = Integer.MIN_VALUE;
            int size = que.size();
            while(size--!=0){
                TreeNode node = que.pollFirst();
                max = Math.max(max,node.val);
                if(node.left!=null){
                    que.addLast(node.left);
                }

                if(node.right!=null){
                    que.addLast(node.right);
                }
                
            }
            res.add(max);
        }
        return res;






    }
}

116.填充每个节点的下一个右侧节点指针

  1. 双指针的思路 来建立每一层的链表指向
  2. 在每一层中用node作为新pop出来的节点作为下一个需要被指向的节点 然后nodepre作为前一个没有被更新的节点
  3. 然后用Nodepre指向Node 最后每一层结束 用Nodepre 指向Null
  4. 然后每一层刚开始 的第一个节点 Node 和 nodepre都赋值 第一个pop出的节点 然后都需要
  5. 然后同样 每次pop出新节点后 也是要看看新节点有没有 左右子节点 有的话 就加在队列的最后段 然后用size控制着每一层的遍历循环
/*
// Definition for a Node.
class Node {
    public int val;
    public Node left;
    public Node right;
    public Node next;

    public Node() {}
    
    public Node(int _val) {
        val = _val;
    }

    public Node(int _val, Node _left, Node _right, Node _next) {
        val = _val;
        left = _left;
        right = _right;
        next = _next;
    }
};
*/

class Solution {
    public Node connect(Node root) {
        Deque<Node> que = new LinkedList<>();
        
        if(root!=null){
            que.addLast(root);
        }

        while(!que.isEmpty()){
            int size = que.size();
            Node nodepre = new Node();
            Node node = new Node();
            for(int i = 0;i<size;i++){
                if(i==0){
                    nodepre = que.pollFirst();
                    node = nodepre;
                    //node = nodepre;
                    if(node.left!=null){
                        que.addLast(node.left);
                    }
                    if(node.right!=null){
                        que.addLast(node.right);
                    }
                }else{
                    node = que.pollFirst();
                    nodepre.next = node;
                    nodepre = nodepre.next;
                    if(node.left!=null){
                        que.addLast(node.left);
                    }
                    if(node.right!=null){
                        que.addLast(node.right);
                    }                   
                }
            
            }
            nodepre.next = null;
        }
        return root;
        
    }
}

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

  1. 此题与上一题类似 同样是用指针指向右边
/*
// Definition for a Node.
class Node {
    public int val;
    public Node left;
    public Node right;
    public Node next;

    public Node() {}
    
    public Node(int _val) {
        val = _val;
    }

    public Node(int _val, Node _left, Node _right, Node _next) {
        val = _val;
        left = _left;
        right = _right;
        next = _next;
    }
};
*/

class Solution {
    public Node connect(Node root) {
        Deque<Node> que = new LinkedList<>();

        if(root!=null){
            que.addLast(root);
        }

        while(!que.isEmpty()){
            int size = que.size();
            Node prenode = new Node();
            Node node = new Node();
            for(int i = 0; i<size;i++){
                if(i==0){
                    prenode = que.pollFirst();
                    node = prenode;
                }else{
                    node = que.pollFirst();
                    prenode.next = node;
                    prenode = prenode.next;
                }
                if(node.left!=null){
                    que.addLast(node.left);
                }
                if(node.right!=null){
                    que.addLast(node.right);
                }


            }
            prenode.next = null;
        }
        return root;
    }
}

104.二叉树的最大深度

  1. 每一层遍历完 depth++
/**
 * Definition for a binary tree node.
 * public 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;
 *     }
 * }
 */
class Solution {
    public int maxDepth(TreeNode root) {
        Deque<TreeNode> que = new LinkedList<>();
        int depth = 0;

        if(root!=null){
            que.addLast(root);
        }

        while(!que.isEmpty()){
            int size = que.size();
            
            while(size--!=0){
                TreeNode node = que.pollFirst();
                if(node.left!=null) que.addLast(node.left);
                if(node.right!=null) que.addLast(node.right);

            }
            depth++;
        }
        return depth;
    }
}

111.二叉树的最小深度

  1. 在每一层遍历中加上判断左节点和右节点是否存在 若都不存在 就直接返回 mindepth
  2. 初始化 Mindepth=1 root存在时
/**
 * Definition for a binary tree node.
 * public 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;
 *     }
 * }
 */
class Solution {
    public int minDepth(TreeNode root) {
        Deque<TreeNode> que = new LinkedList<>();


        

        int mindepth = 1;
        if(root!=null){
            que.addLast(root);
        }else{
            return 0;
        }

        while(!que.isEmpty()){
            int size = que.size();
            while(size--!=0){
                TreeNode node = que.pollFirst();
                if(node.left==null && node.right==null) return mindepth;
                if(node.left!=null) que.addLast(node.left);
                if(node.right!=null) que.addLast(node.right);                
            }
            mindepth++;

        }
        return mindepth;
    }
}

226.翻转二叉树

  1. 思路比较清楚 就是去遍历每一个节点 让每一个节点交换左右子节点
  2. 前中后递归遍历 通过自己模拟一遍流程 发现 前后序遍历可以翻转 但是 中序遍历翻转较为麻烦
  3. 此外就是递归三部曲
    1. 参数传入 节点
    2. 结束条件 当节点为空 开始返回
    3. 逻辑操作 为前序或者后序

前序递归

/**
 * Definition for a binary tree node.
 * public 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;
 *     }
 * }
 */
class Solution {
    public TreeNode invertTree(TreeNode root) {
        // if(root==null) return root;
        preorder(root);
        return root;



    }

    public void preorder(TreeNode node){
        if(node==null) return;
        //中左右
        //交换左右子节点
        TreeNode temp = node.left;
        node.left = node.right;
        node.right = temp;
        preorder(node.left);
        preorder(node.right);
    }
}

广度优先遍历 层序遍历

  1. 每一层都反转他们的子节点 也可以 这样也能遍历完所有节点
/**
 * Definition for a binary tree node.
 * public 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;
 *     }
 * }
 */
class Solution {
    public TreeNode invertTree(TreeNode root) {
        //广度优先搜索 层序遍历 用一个辅助队列
        Deque<TreeNode> que = new LinkedList<>();
        if(root!=null) que.addLast(root);
        while(!que.isEmpty()){
            int size  = que.size();
            while(size--!=0){
                TreeNode node = que.pollFirst();
                swap(node);
                if(node.left!=null) que.addLast(node.left);
                if(node.right!=null) que.addLast(node.right);                
            }
        }
        return root;




    }

    public void swap(TreeNode node){
        TreeNode temp = node.left;
        node.left = node.right;
        node.right = temp;
    }

}

101. 对称二叉树

  1. 要相对于中轴线 比较 外侧节点是否相等 内侧节点是否相等 外侧节点 为左边子树的左节点 右边子树的右节点
  2. 遍历方式选择 后序遍历 因为这样才可以处理判断完 两个左右子节点 是否相等 然后再return
  3. 创建一个compare函数 判断有哪些情况为true false 左为空 右不为空 false 左不为空 右为空 false 左边右边值不相等 false
  4. 递归三部曲中 传入的参数 为根节点的左子树和 根节点的右子树 就是比较他们是否对称
  5. 终止条件
    1. 左为空 右不为空 false
    2. 左不为空 右为空 false
    3. 左为空 右为空 true 因为下面没有节点可以继续向下遍历了 所以直接return
    4. 左不为空 右不为空 但是值不相等 false
    5. 左不为空 右不为空 值相等不能作为终止条件 因为这种情况还要继续向下面遍历 是递归三部曲的第三部
  6. 递归的第三步 逻辑操作 后序遍历顺序 左右中 获取到外侧 和 内侧 的返回值 然后 判断外侧和内侧是否都true 然后往上面返回 即左右中 左右就是继续往下面遍历 中就是处理当前节点的情况
/**
 * Definition for a binary tree node.
 * public 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;
 *     }
 * }
 */
class Solution {
    public boolean isSymmetric(TreeNode root) {
        return compare(root.left,root.right);

    }

    public boolean compare(TreeNode left,TreeNode right){
        //终止条件return
        if(left==null && right!=null) return false;
        if(right==null && left!=null) return false;   
        if(left==null && right==null) return true;     
        if(left.val!=right.val) return false;
        

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

    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值