代码随想录算法训练营第13天 | 复习二叉树基础

2024年7月15日

二叉树
前序遍历,前就是指根在前,递归要注意判断节点为空。
如果不用递归,就用一个栈来保存节点。

/**
 * 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> preorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        return first(root,list);
    }

    public List<Integer> first(TreeNode root, List<Integer> list){
        if(root==null){
            return list;
        }
        list.add(root.val);
        if(root.left!=null){
            list = first(root.left,list);
        }
        if(root.right!=null){
            list = first(root.right,list);
        }
        return list;
    }
}

后序,就是根最后。

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        return back(root,list);
    }

    public List<Integer> back(TreeNode root, List<Integer> list){
        if(root==null){
            return list;
        }
        if(root.left!=null){
            list = back(root.left,list);
        }
        if(root.right!=null){
            list = back(root.right,list);
        }
        list.add(root.val);
        return list;
    }
}

中序,就是根节点在中间。

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        return med(root,list);
    }

    public List<Integer> med(TreeNode root, List<Integer> list){
        if(root==null){
            return list;
        }
        
        if(root.left!=null){
            list = med(root.left,list);
        }
        list.add(root.val);
        if(root.right!=null){
            list = med(root.right,list);
        }
        return list;
    }
}

迭代遍历
前序,就要先把root加入,然后进入while循环,每次循环先取一个,如果不空,就加入结果并压入右和左(返回来压才是左先出)

class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        //用一个栈存放节点
        //前序遍历就是根左右
        //队列实现,先放左再放右
        //从队列取出来的时候就是遍历其右子树
        List<Integer> res = new ArrayList<>();
        if(root==null){
            return res;
        }
        
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        // res.add(root.val);
        TreeNode q = root.left;
        while(!stack.isEmpty()){
            q = stack.pop();
            if(q!=null){
                res.add(q.val);
                stack.push(q.right);
                stack.push(q.left);
            }
        }
        return res;
    }

}

中序遍历
左根右,那么就是先将right,root和left依次入栈,然后进入循环,每次先取出,如果不为空,就再次将right,root和left依次入栈;如果为空,就说明左侧到终点了。此时首先判断栈是否为空,如果不为空就先取出一个,并放入结果,然后continue即可。

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        //中序就是左根右
        List<Integer> res = new ArrayList<>();
        if(root==null){
            return res;
        }
        
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root.right);
        stack.push(root);
        stack.push(root.left);
        TreeNode q;
        while(!stack.isEmpty()){
            q = stack.pop();
            if(q!=null){
                stack.push(q.right);
                stack.push(q);
                stack.push(q.left);
            }else{
                if(!stack.isEmpty()){
                    q = stack.pop();
                    res.add(q.val);
                }
            }
        }
        return res;
    }
}

后序遍历
左右根,首先按照根右左的顺序压root及其右左,然后将root的左右指针设置为null,这么做的目的是让后序循环不会反复上下死循环。然后进入循环取出q,判断其是为空。如果不为空,就再次判断其是否同时没有左右子树。如果都没有,就输出其,并continue;否则再次按照q及其右左子树压入栈,并将左右指针设null。

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        //后序就是左右根
        List<Integer> res = new ArrayList<>();
        if(root==null){
            return res;
        }
        
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        stack.push(root.right);
        stack.push(root.left);
        root.left=null;
        root.right=null;
        TreeNode q;
        while(!stack.isEmpty()){
            q = stack.pop();
            if(q!=null){
                if(q.left==null && q.right==null){
                    res.add(q.val);
                    continue;
                }
                else{
                    stack.push(q);
                    stack.push(q.right);
                    stack.push(q.left);
                    q.left=null;
                    q.right=null;
                }
            }
        }
        return res;
    }
}

题102. 二叉树的层序遍历
用height记录,递归遍历的时候用前序遍历就是从左到右,遍历的同时记录即可。

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> res = new ArrayList<>();
        if(root==null){
            return res;
        }
        //用根左右遍历,每次记录高度
        int height=0;
        res = digui(res,height,root);
        return res;
    }

    public List<List<Integer>> digui(List<List<Integer>> res,int height,TreeNode p){
        if(res.size()<height+1){
            List<Integer> res1 = new ArrayList<>();
            res.add(res1);
        }
        int val = p.val;
        res.get(height).add(val);
        if(p.left!=null){
            res = digui(res,height+1,p.left);
        }
        if(p.right!=null){
            res = digui(res,height+1,p.right);
        }
        return res;
    }
}

题107. 二叉树的层次遍历II
可以用头插法,也可以直接倒序。

题199. 二叉树的右视图
可以用层序遍历之后,取出每一层的最后一个元素即可。

class Solution {
    public List<Integer> rightSideView(TreeNode root) {
        List<List<Integer>> res = new ArrayList<>();
        List<Integer> res2 = new ArrayList<>();
        if(root==null){
            return res2;
        }
        //用根左右遍历,每次记录高度
        int height=0;
        res = digui(res,height,root);
        
        for(List<Integer> v:res){
            res2.add(v.get(v.size()-1));
        }
        return res2;
    }

    public List<List<Integer>> digui(List<List<Integer>> res,int height,TreeNode p){
        if(res.size()<height+1){
            List<Integer> res1 = new ArrayList<>();
            res.add(res1);
        }
        int val = p.val;
        res.get(height).add(val);
        if(p.left!=null){
            res = digui(res,height+1,p.left);
        }
        if(p.right!=null){
            res = digui(res,height+1,p.right);
        }
        return res;
    }
}

题637. 二叉树的层平均值
使用层序遍历后即可求平均。

题429. N叉树的层序遍历

/*
// 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<>();
        if(root==null){
            return res;
        }
        //用根左右遍历,每次记录高度
        int height=0;
        res = digui(res,height,root);
        return res;
    }

    public List<List<Integer>> digui(List<List<Integer>> res,int height,Node p){
        if(res.size()<height+1){
            List<Integer> res1 = new ArrayList<>();
            res.add(res1);
        }
        int val = p.val;
        res.get(height).add(val);
        for(Node p1:p.children){
            res = digui(res,height+1,p1);
        }
        return res;
    }
}

题515. 在每个树行中找最大值
继续使用层序遍历的模板。
记住API是Integer.MIN_VALUE。

class Solution {
    public List<Integer> largestValues(TreeNode root) {
        List<List<Integer>> res = new ArrayList<>();
        List<Integer> res2 = new ArrayList<>();
        if(root==null){
            return res2;
        }
        //用根左右遍历,每次记录高度
        int height=0;
        res = digui(res,height,root);
        
        for(List<Integer> v:res){
            int max = Integer.MIN_VALUE;
            for(int i=0;i<v.size();i++){
                if(v.get(i)>max){
                    max = v.get(i);
                }
            }
            res2.add(max);
        }
        return res2;
    }

    public List<List<Integer>> digui(List<List<Integer>> res,int height,TreeNode p){
        if(res.size()<height+1){
            List<Integer> res1 = new ArrayList<>();
            res.add(res1);
        }
        int val = p.val;
        res.get(height).add(val);
        if(p.left!=null){
            res = digui(res,height+1,p.left);
        }
        if(p.right!=null){
            res = digui(res,height+1,p.right);
        }
        return res;
    }
}

题116. 填充每个节点的下一个右侧节点指针
题117. 填充每个节点的下一个右侧节点指针 II
先使用层序遍历记下每个节点,然后遍历每一层并加上指针即可,两个题可以用一样的代码。

class Solution {
    public Node connect(Node root) {
        List<List<Node>> res = new ArrayList<>();
        if(root==null){
            return root;
        }
        //用根左右遍历,每次记录高度
        int height=0;
        res = digui(res,height,root);
        for(List<Node> list:res){
            for(int i=0;i<list.size();i++){
                if(i==list.size()-1){
                    list.get(i).next=null;
                }else{
                    list.get(i).next=list.get(i+1);
                }
            }
        }
        return root;
    }

    public List<List<Node>> digui(List<List<Node>> res,int height,Node p){
        if(res.size()<height+1){
            List<Node> res1 = new ArrayList<>();
            res.add(res1);
        }
        
        res.get(height).add(p);
        if(p.left!=null){
            res = digui(res,height+1,p.left);
        }
        if(p.right!=null){
            res = digui(res,height+1,p.right);
        }
        return res;
    }
}

题104. 二叉树的最大深度
层序遍历后返回list长度即可,注意判断root为空就返回0。

题111. 二叉树的最小深度
用一个属性来记录,当左右子树都为null时,就记录当前高度。如果更小,就记下来。

class Solution {

    public int minHeight;

    public int minDepth(TreeNode root) {
            List<List<Integer>> res = new ArrayList<>();
        if(root==null){
            return 0;
        }
        minHeight=Integer.MAX_VALUE;
        //用根左右遍历,每次记录高度
        int height=0;
        res = digui(res,height,root);
        return minHeight;
    }

    public List<List<Integer>> digui(List<List<Integer>> res,int height,TreeNode p){
        if(res.size()<height+1){
            List<Integer> res1 = new ArrayList<>();
            res.add(res1);
        }
        int val = p.val;
        res.get(height).add(val);
        if(p.left==null && p.right==null){
            if(minHeight>height+1){
                minHeight=height+1;
            }
            return res;
        }
        if(p.left!=null){
            res = digui(res,height+1,p.left);
        }
        if(p.right!=null){
            res = digui(res,height+1,p.right);
        }
        return res;
    }
}
posted @ 2024-07-15 21:56  hailicy  阅读(0)  评论(0编辑  收藏  举报