144. 二叉树的前序遍历

深度优先搜索

import java.util.ArrayList;
import java.util.List;

class Solution {

    List list = new ArrayList();

    public List<Integer> preorderTraversal(TreeNode root) {

        if (root == null) {
            return list;
        }

        /**
         * 先记录根节点值,然后对左右孩子进行递归(隐式栈)
         */
        list.add(root.val);
        preorderTraversal(root.left);
        preorderTraversal(root.right);

        return list;
    }
}

/**
 * 时间复杂度 O(n)
 * 空间复杂度 O(n)
 */

迭代

因为前序遍历的顺序是中左右,先访问的元素是中间节点,要处理的元素也是中间节点,处理顺序和访问顺序是一致的,所以能写出相对简洁的代码

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

class Solution {

    List<Integer> list = new ArrayList<>();

    public List<Integer> preorderTraversal(TreeNode root) {

        if (root == null){
            return list;
        }

        /**
         * 迭代实现前序遍历
         * 将根节点压入栈后,开始循环(显式栈)
         * 先弹出根节点,记录值,然后依次压入右孩子和左孩子(如果存在的话),依次类推,直到栈空
         */
        Stack<TreeNode> stack = new Stack<>();

        stack.push(root);

        while (!stack.isEmpty()){

            TreeNode temp = stack.pop();
            list.add(temp.val);

            if (temp.right != null){
                stack.push(temp.right);
            }

            if (temp.left != null){
                stack.push(temp.left);
            }
        }

        return list;
    }
}

/**
 * 时间复杂度 O(n)
 * 空间复杂度 O(n)
 */

迭代2

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

class Solution {

    List<Integer> list = new ArrayList<>();

    public List<Integer> preorderTraversal(TreeNode root) {

        if (root == null){
            return list;
        }

        Stack<TreeNode> stack = new Stack<>();
        TreeNode cur = root;

        while (cur != null || !stack.isEmpty()){

            if (cur != null){

                list.add(cur.val);
                stack.push(cur);
                cur = cur.left;
            }
            else{
                
                cur = stack.pop();
                cur = cur.right;
            }
        }

        return list;
    }
}

/**
 * 时间复杂度 O(n)
 * 空间复杂度 O(n)
 */

统一迭代写法

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

class Solution {

    List<Integer> list = new ArrayList<>();

    public List<Integer> preorderTraversal(TreeNode root) {

        if (root == null){
            return list;
        }

        Stack<Command> stack = new Stack<>();

        /**
         * 首先压入根节点,但不进行打印
         */
        stack.push(new Command(false, root));

        while (!stack.isEmpty()){

            /**
             * 每次弹出栈顶节点进行判断
             * 如果是上一轮的根节点,就打印;否则按不同顺序压入其左右孩子和本身
             */
            Command command = stack.pop();

            if (command.isPrint){
                list.add(command.node.val);
            }
            else {

                /**
                 * 前序遍历
                 * 先将右孩子、左孩子压入栈,然后再压入根节点,让弹出的顺序变为根节点、左孩子、右孩子
                 * 其中根节点的isPrint == true
                 */
                if (command.node.right != null){
                    stack.push(new Command(false, command.node.right));
                }

                if (command.node.left != null){
                    stack.push(new Command(false, command.node.left));
                }

                stack.push(new Command(true, command.node));
            }
        }

        return list;
    }
}

/**
 * 为了像递归写法一样统一前中后序遍历,将压入栈的元素定义为一个Command类
 * 其中包含要处理的当前节点,还有要进行的操作
 * isPrint == true代表将当前节点的值打印出来,添加进列表,否则就遍历到其左右孩子
 */
class Command{

    Boolean isPrint;
    TreeNode node;
    Command(Boolean isPrint, TreeNode node){

        this.isPrint = isPrint;
        this.node = node;
    }
}

/**
 * 时间复杂度 O(n)
 * 空间复杂度 O(n)
 */

https://leetcode-cn.com/problems/binary-tree-preorder-traversal/

posted @ 2021-10-27 20:19  振袖秋枫问红叶  阅读(42)  评论(0)    收藏  举报