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;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章