【小Y学算法】⚡️每日LeetCode打卡⚡️——39.二叉树的前序遍历

????前言

???? 算法题 ????

???? 每天打卡一道算法题,既是一个学习过程,又是一个分享的过程????

???? 提示:本专栏解题 编程语言一律使用 C# 和 Java 两种进行解题

???? 要保持一个每天都在学习的状态,让我们一起努力成为算法大神吧????!

???? 今天是力扣算法题持续打卡第39天????!

???? 算法题 ????

????原题样例:二叉树的前序遍历

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


示例 1:

【小Y学算法】⚡️每日LeetCode打卡⚡️——39.二叉树的前序遍历

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

示例 2:

输入:root = []
输出:[]

示例 3:

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

示例 4:

【小Y学算法】⚡️每日LeetCode打卡⚡️——39.二叉树的前序遍历

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

示例 5:

【小Y学算法】⚡️每日LeetCode打卡⚡️——39.二叉树的前序遍历

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

提示:

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


????C#方法:递归

思路解析

快慢指针,快慢指针同时从头节点出发,快指针每次走两步,慢指针每次走一步,如果存在环的话,快指针迟早赶上慢指针。

代码:

public class Solution 
{
    private IList<int> res = new List<int>();

    public IList<int> PreorderTraversal(TreeNode root) 
    {
        Traversal(root);
        return res;
    }

    private void Traversal(TreeNode node)
    {
        if(node!=null)
        {
            res.Add(node.val);
            PreorderTraversal(node.left);
            PreorderTraversal(node.right);
        }
    }
}

执行结果

通过
执行用时:224 ms,在所有 C# 提交中击败了70.79%的用户
内存消耗:29.8 MB,在所有 C# 提交中击败了79.47%的用户

????Java 方法一:递归

思路解析


首先我们需要了解什么是二叉树的前序遍历:按照访问根节点——左子树——右子树的方式遍历这棵树,而在访问左子树或者右子树的时候,我们按照同样的方式遍历,直到遍历完整棵树。


因此整个遍历过程天然具有递归的性质,我们可以直接用递归函数来模拟这一过程。


定义preorder(root)表示当前遍历到 root节点的答案。按照定义,我们只要首先将root 节点的值加入答案,然后递归调用 preorder(root.left)来遍历root节点的左子树,最后递归调用preorder(root.right)来遍历 root节点的右子树即可,递归终止的条件为碰到空节点。


代码:

class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<Integer>();
        preorder(root, res);
        return res;
    }

    public void preorder(TreeNode root, List<Integer> res) {
        if (root == null) {
            return;
        }
        res.add(root.val);
        preorder(root.left, res);
        preorder(root.right, res);
    }
}

执行结果

通过
执行用时:0 ms,在所有 Java  提交中击败了100.00%的用户
内存消耗:36.6 MB,在所有 Java 提交中击败了59.89%的用户
• 1
• 2
• 3

复杂度分析

时间复杂度:O( n ),其中 n 是二叉树的节点数
空间复杂度:O( n )

????Java 方法一:迭代

思路解析

我们也可以用迭代的方式实现方法一的递归函数,两种方式是等价的,区别在于递归的时候隐式地维护了一个栈,

而我们在迭代的时候需要显式地将这个栈模拟出来,其余的实现与细节都相同,具体可以参考下面的代码

代码:

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

        Deque<TreeNode> stack = new LinkedList<TreeNode>();
        TreeNode node = root;
        while (!stack.isEmpty() || node != null) {
            while (node != null) {
                res.add(node.val);
                stack.push(node);
                node = node.left;
            }
            node = stack.pop();
            node = node.right;
        }
        return res;
    }
}

执行结果

通过
执行用时:0 ms,在所有 Java  提交中击败了100.00%的用户
内存消耗:36.9 MB,在所有 Java 提交中击败了5.45%的用户

复杂度分析

时间复杂度:O( n ),其中 n 是二叉树的节点数
空间复杂度:O( n )
• 1
• 2

????总结

  • 今天是力扣算法题打卡的第三十九天!
  • 文章采用 C#Java 两种编程语言进行解题
  • 一些方法也是参考力扣大神写的,也是边学习边分享,再次感谢算法大佬们
上一篇:SLS投递OSS功能升级:打造更顺畅的日志入湖体验


下一篇:nodejs与javascript中的aes加密