leetcode高频题笔记之树的遍历

概要:
采用递归,状态标记迭代,普通迭代三种方法实现了二叉树的前中后序遍历

状态标记法的思路来源于题解颜色标记法

其中,递归和颜色标记法的前中后序遍历都非常相似,只需要记忆一个就可以了!

二叉树的中序遍历(3种实现)

在这里插入图片描述

递归实现

public class Solution {

    List<Integer> res;

    public List<Integer> inorderTraversal(TreeNode root) {

        res = new ArrayList<>();
        helper(root);
        return res;
    }

    private void helper(TreeNode root) {
        if (root == null) return;
        helper(root.left);
        res.add(root.val);
        helper(root.right);
    }
}

状态标记法迭代实现

public class Solution {
    
    //加强的node类,加上了node是否被遍历过了的标记
    class IncreaseNode {
        TreeNode node;
        boolean is_finish;//是否已经遍历过了

        public IncreaseNode(TreeNode node, boolean is_finish) {
            this.node = node;
            this.is_finish = is_finish;
        }
    }

    public List<Integer> inorderTraversal(TreeNode root) {
        if (root == null) return new ArrayList<>();

        List<Integer> res = new ArrayList<>();
        Stack<IncreaseNode> stack = new Stack<>();
        stack.push(new IncreaseNode(root, false));

        while (!stack.isEmpty()) {
            IncreaseNode inode = stack.pop();

            if (!inode.is_finish) {
                //注意: 压栈顺序和排序方式是相反的
                if (inode.node.right != null) stack.push(new IncreaseNode(inode.node.right, false));
                stack.push(new IncreaseNode(inode.node, true));
                if (inode.node.left != null) stack.push(new IncreaseNode(inode.node.left, false));
            } else {
                res.add(inode.node.val);
            }
        }
        return res;
    }

}

普通迭代实现

public class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        if (root == null) return new ArrayList<>();

        List<Integer> res = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        TreeNode cur = root;
        while (cur != null || !stack.isEmpty()) {
            //存在左节点,就一直压栈
            while (cur!=null){
                stack.push(cur);
                cur = cur.left;
            }
            cur = stack.pop();
            res.add(cur.val);
            cur = cur.right;
        }
        return res;
    }
}

二叉树的前序遍历(3种实现)

在这里插入图片描述

递归实现

class Solution {
    List<Integer> res;

    public List<Integer> preorderTraversal(TreeNode root) {
        res = new ArrayList<>();
        helper(root);
        return res;
    }

    private void helper(TreeNode root) {
        if (root == null) return;
        res.add(root.val);
        helper(root.left);
        helper(root.right);
    }
}

状态标记法迭代实现

public class Solution {

    //加强的node类,加上了node是否被遍历过了的标记
    class IncreaseNode {
        TreeNode node;
        boolean is_finish;//是否已经遍历过了

        public IncreaseNode(TreeNode node, boolean is_finish) {
            this.node = node;
            this.is_finish = is_finish;
        }
    }

    public List<Integer> preorderTraversal(TreeNode root) {
        if (root==null)return new ArrayList<>();
        
        List<Integer> res = new ArrayList<>();
        Stack<IncreaseNode> stack = new Stack<>();
        stack.push(new IncreaseNode(root, false));

        while (!stack.isEmpty()) {
            IncreaseNode cur = stack.pop();

            if (!cur.is_finish){
                if (cur.node.right!=null)stack.push(new IncreaseNode(cur.node.right,false));
                if (cur.node.left!=null)stack.push(new IncreaseNode(cur.node.left,false));
                stack.push(new IncreaseNode(cur.node,true));
            }else {
                res.add(cur.node.val);
            }
        }
        return res;
    }
}

普通迭代实现

class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        if (root == null) return new ArrayList<>();
       
        List<Integer> res = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode cur = stack.pop();
            if (cur == null) {
                continue;
            }
            res.add(cur.val);
            stack.push(cur.right);
            stack.push(cur.left);
        }
        return res;
    }
}

二叉树的后序遍历(3种实现)

在这里插入图片描述

递归实现

class Solution {
    List<Integer> res;

    public List<Integer> postorderTraversal(TreeNode root) {
        res = new ArrayList<>();
        helper(root);
        return res;
    }

    private void helper(TreeNode root) {
        if (root == null)return;
        helper(root.left);
        helper(root.right);
        res.add(root.val);
    }
}

状态标记法迭代实现

class Solution {
    //加强的node类,加上了node是否被遍历过了的标记
    class IncreaseNode {
        TreeNode node;
        boolean is_finish;

        public IncreaseNode(TreeNode node, boolean is_finish) {
            this.node = node;
            this.is_finish = is_finish;//是否已经遍历过了
        }
    }

    public List<Integer> postorderTraversal(TreeNode root) {
        if (root == null) return new ArrayList<>();
        List<Integer> res = new ArrayList<>();
        Stack<IncreaseNode> stack = new Stack<>();
        stack.push(new IncreaseNode(root, false));

        while (!stack.isEmpty()) {
            IncreaseNode cur = stack.pop();

            if (!cur.is_finish) {
                stack.push(new IncreaseNode(cur.node, true));
                if (cur.node.right != null) stack.push(new IncreaseNode(cur.node.right, false));
                if (cur.node.left != null) stack.push(new IncreaseNode(cur.node.left, false));

            } else {
                res.add(cur.node.val);
            }
        }
        return res;
    }
}

普通迭代实现

后序遍历的普通迭代太难想了,所以采用取巧的方式实现

我们能很容易写出来的是前序遍历的普通迭代
前序遍历是:根-左-右
后序遍历是:左-右-根
左右在里面都是等价的,所以我们把前序的left和right对换一下,然后将结果逆序,就是左-右-根

class Solution {

    public List<Integer> postorderTraversal(TreeNode root) {

        if (root == null) return new ArrayList<>();

        List<Integer> res = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode cur = stack.pop();
            if (cur == null) {
                continue;
            }
            res.add(cur.val);
            stack.push(cur.left);
            stack.push(cur.right);
        }
        
        Collections.reverse(res);
        return res;
    }
}



或者

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {

        if (root == null) return new ArrayList<>();

        LinkedList<Integer> res = new LinkedList<>();
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode cur = stack.pop();
            if (cur == null) {
                continue;
            }
            res.addFirst(cur.val);
            stack.push(cur.left);
            stack.push(cur.right);
        }
        return res;
    }
}

二叉树的层序遍历

在这里插入图片描述
BFS实现

class Solution {
     public List<List<Integer>> levelOrder(TreeNode root) {
        if (root == null) return new ArrayList<>();
        LinkedList<TreeNode> queue = new LinkedList<>();
        List<List<Integer>> res = new ArrayList<>();
        queue.offerLast(root);
        while (!queue.isEmpty()) {
            int size = queue.size();
            List<Integer> tmpList = new ArrayList<>();
            for (int i = 0; i < size; i++) {
                TreeNode cur = queue.pollFirst();
                tmpList.add(cur.val);
                if (cur.left != null) queue.offerLast(cur.left);
                if (cur.right != null) queue.offerLast(cur.right);
            }
            res.add(tmpList);
        }
        return res;
    }
}

N叉树的前序遍历

在这里插入图片描述

递归实现

public class Solution {
    List<Integer> res;

    public List<Integer> preorder(Node root) {
        res = new ArrayList<>();
        helper(root);
        return res;
    }

    private void helper(Node root) {
        if (root == null) return;
        res.add(root.val);
        for (Node node : root.children) {
            helper(node);
        }
    }
}

迭代实现

class Solution {
    public List<Integer> preorder(Node root) {

        if (root == null) return new ArrayList<>();

        Stack<Node> stack = new Stack<Node>();
        List<Integer> res = new ArrayList<>();

        stack.push(root);

        while (!stack.isEmpty()) {
            Node cur = stack.pop();
            res.add(cur.val);
            for (int i = cur.children.size() - 1; i >= 0; i--) {
                if (cur.children.get(i)!=null){
                    stack.push(cur.children.get(i));
                }
            }
        }
        return res;
    }
}

N叉树的后序遍历

在这里插入图片描述

递归实现

public class Solution {
    List<Integer> res;

    public List<Integer> postorder(Node root) {
        res = new ArrayList<>();
        helper(root);
        return res;
    }

    private void helper(Node root) {
        if (root == null) return;

        for (Node node : root.children) {
            helper(node);
        }
        res.add(root.val);
    }
}

迭代实现

public class Solution {
    
    public List<Integer> postorder(Node root) {

        if (root == null) return new ArrayList<>();

        Stack<Node> stack = new Stack<Node>();
        LinkedList<Integer> res = new LinkedList<>();

        stack.push(root);

        while (!stack.isEmpty()) {
            Node cur = stack.pop();
            res.addFirst(cur.val);
            //为什么从左往右压栈:addFirst从右侧开始加,最终是左右根,加完了根就先右
            for (int i = 0; i < cur.children.size(); i++) {
                if (cur.children.get(i) != null) {
                    stack.push(cur.children.get(i));
                }
            }
        }
        return res;
    }
}

N叉树的层序遍历

在这里插入图片描述
BFS实现

public class Solution {
    public List<List<Integer>> levelOrder(Node root) {
        List<List<Integer>> res = new LinkedList<>();
        if (root == null) return res;//root为空特殊情况
        Deque<Node> deque = new LinkedList<Node>();
        deque.offer(root);
        while (!deque.isEmpty()) {
            int size = deque.size();
            //每一层临时集合
            List<Integer> tmpList = new LinkedList<>();
            for (int i = 0; i < size; i++) {
                Node cur = deque.poll();
                tmpList.add(cur.val);
                for (Node node : cur.children) {
                    if (node != null)//剪枝
                        deque.offer(node);
                }
            }
            res.add(tmpList);
        }
        return res;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章