LeetCode 144. 二叉树的前序遍历

LeetCode 144. 二叉树的前序遍历

 

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

示例 1:

输入:root = [1,null,2,3]
输出:[1,2,3]


示例 2:
输入:root = []
输出:[]

示例 3:
输入:root = [1]
输出:[1]

示例 4:

输入:root = [1,2]
输出:[1,2]

示例 5:

输入:root = [1,null,2]
输出:[1,2]

提示:

树中节点数目在范围 [0, 100] 内
-100 <= Node.val <= 100
 

进阶:递归算法很简单,你可以通过迭代算法完成吗?

思路:

  • 迭代:
    • 利用栈(数组)实现,从根节点开始不断向下遍历左子节点,并且将每个节点入栈,直至左子节点不存在(为空)。
    • 接下来,获取栈顶的节点top,获取top的右子节点,从栈中弹出栈顶节点top
    • 以top节点为基准,找top的左子节点,重新开始新一轮遍历
      根节点 -> 左子节点(不断向下直至左子节点为空) -> 弹出栈顶节点top -> 获取top右子节点 -> 栈顶元素出栈 -> 以top从头开始新一轮左子节点遍历 -> ...
  • 递归

时间复杂度:
O(n),其中 n 是二叉树的节点数,每个节点都遍历到。

空间复杂度: 
O(n),为迭代过程中显式栈的开销,平均情况下为 O(log n),最坏情况下树呈现链状,为 O(n)。

Go版本:

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
// 方法1 迭代
func preorderTraversal(root *TreeNode) []int {
    array := make([]int, 0)
    stack := make([]*TreeNode, 0)
    for root != nil || len(stack) > 0 {
        // 不断遍历左子树
        for root != nil {
            array = append(array, root.Val) // result, finally return 
            stack = append(stack, root)     // push
            root = root.Left
        }
        // 左子树遍历完了,开始从下往上遍历右子树(每次找栈顶指针,然后pop出栈)
        if len(stack) > 0 {
            root = stack[len(stack) - 1]    // 获取栈顶元素
            root = root.Right
            stack = stack[: len(stack) - 1] // pop
        }
    }

    return array
}

// 方法2 递归
var array []int
func preorderTraversal(root *TreeNode) []int {
    array = make([]int, 0)
    dfs(root)
    return array
}

func dfs(root *TreeNode) {
    if root == nil {
        return
    }

    array = append(array, root.Val)
    dfs(root.Left)
    dfs(root.Right)
}

C++版本:

vector<int> preorderTraversal(TreeNode* root) {
        vector<int> v;
        stack<TreeNode*> s;
        while (root != NULL || !s.empty())       // 注意是||不是&&
        {
            while (root != NULL)
            {
                v.push_back(root->val);          // cout
                s.push(root);
                root = root->left;
            }
            // 若跳出上面循环,表示当前节点的left节点为NULL
            if (!s.empty())
            {
                // 接下来寻找当前节点的right节点,并且当前root节点已无作用->pop
                root = s.top();
                s.pop();
                root = root->right;
            }
        }
 
        return v;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值