[路飞]_leetcode刷题_144. 二叉树的前序遍历

328 阅读3分钟

「这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战

题目

给你二叉树的根节点 root ,返回它节点值的 前序 **遍历。

 

示例 1:

image.png

递归解法:

先传入根节点root和初始化结果数组res=[],若root不为空,则res.push(root.val),然后递归调用自身并传入root.left,处理完左节点后,递归调用处理右节点root.right

递归解法代码:

/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var preorderTraversal = function(root,res=[]) {
    if(root == null){
        return res;
    } 

    res.push(root.val)
    preorderTraversal(root.left,res)
    preorderTraversal(root.right,res)
    return res
};

迭代解法:

递归的方法,相当于系统维护了一个栈,每次递归调用的时候,就把剩下的代码逻辑存到栈中,等递归到最后一层后,开始往外弹,再一层一层去执行存在栈中的剩下逻辑代码。

那么迭代的解法,就需要自己去维护一个栈,二叉树的前序遍历,是根左右的遍历顺序,那么我们每次遍历根节点后,依次将右节点、左节点压入栈,然后再从栈中取出左节点,当作新的“根节点”,再将新的右节点、左节点压入栈中以此类推。

迭代解法代码:

/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var preorderTraversal = function(root,res=[]) {
    if(root == null){
        return res;
    } 

    let stack = [];
    stack.push(root);
    while(stack.length>0){
        let node = stack[stack.length - 1];
        stack.pop();
        res.push(node.val);
        if(node.right){
            stack.push(node.right);
        }
        if(node.left){
            stack.push(node.left);
        }
    }
    return res
};

morris解法:

思路:

设立两个指针,p1p2,p1指向当前遍历节点,p2指向p1左叶的最右子节点。正常来说,未经处理的p2节点,应该p2 != null && p2.right == null,或者直接是p2 ==null

p2 的状态有以下三种:

  1. 如果p2 != null && p2.right==null,则说明该节点第一次来,还没有构建返回指针,那么让p2.right=p1,并且打印p1的值。循环该操作,将左侧所有右侧末尾节点都构建上返回指针。

  2. 如果p2 == null,则说明p1已经走到自身左叶左节点最末尾,那么就打印p1的值,并让p1往右走,即p1 = p1.right,由于p1目前的节点在上一步就已经构建了返回路径指针,所以可以正常回到自身所处的树的根节点的根节点

  3. 如果p2 !== null && p2.right !== nul,那么说明p2曾已经已经来过,并且构建过返回指针,并且这时候p1肯定已经从这个节点走过了,那么就让p2.right == null,而且此时的p1正处在目前p2所在的树的根节点的根节点,这个节点在一开始就打印过,所以这次不用打印,让p1继续往右走,p1 = right

重复循环上述操作,即可完成遍历。

总的来说,p2就这三种状态,整个遍历也是围绕的p2的状态来走的。

这里回头我会补一个动画分解图。

代码实现如下:

/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var preorderTraversal = function(root,res=[]) {
    if(root == null){
        return res;
    } 

    let p1 = root;
    let p2 = null;
    while(p1 != null){
        p2 = p1.left;
        if(p2 != null){
            while(p2.right != null && p2.right != p1){
                p2 = p2.right;
            }
            if(p2.right == null){
                res.push(p1.val);
                p2.right = p1;
                p1 = p1.left;
                continue;
            }
            p2.right = null;
        }else{
            res.push(p1.val);
        }
        p1 = p1.right;
    }
    return res;
};