刷题笔记:力扣第144题-二叉树的前序遍历

1.本题考查二叉树的前序遍历,前序遍历的意思为一开始就遍历读取根节点的值,遍历顺序为"根-左-右"。本题先使用递归算法,返回值为void,因为每个节点的值会被存放到已经开辟的结果数组空间中,每次只需要传入当前节点的指针以及结果数组即可。完整代码如下:

cpp 复制代码
 1. /**
 2.  * Definition for a binary tree node.
 3.  * struct TreeNode {
 4.  *     int val;
 5.  *     struct TreeNode *left;
 6.  *     struct TreeNode *right;
 7.  * };
 8.  */
 9. /**
10.  * Note: The returned array must be malloced, assume caller calls free().
11.  */
12. // 全局变量,记录结果数组当前存放元素的下标
13. int cur;
14. // 递归回溯函数,二叉树前序遍历:根 -> 左 -> 右
15. void backTrack(struct TreeNode* node, int* res){
16.     // 递归终止条件:当前节点为空直接返回
17.     if (node == NULL) return;
18.     // 访问根节点,存入结果数组
19.     res[cur++] = node->val;
20.     // 递归遍历左子树
21.     backTrack(node->left, res);
22.     // 递归遍历右子树
23.     backTrack(node->right, res);
24. }
25. // 二叉树前序遍历入口函数
26. int* preorderTraversal(struct TreeNode* root, int* returnSize) {
27.     // 分配结果数组空间,固定大小101
28.     int* res = (int*)malloc(sizeof(int) * 101);
29.     // 初始化下标计数器
30.     cur = 0;
31.     // 启动递归遍历
32.     backTrack(root, res);
33.     // 设置返回数组长度
34.     *returnSize = cur;
35.     return res;
36. }

该算法时间复杂度和空间复杂度均为O(n)。

2.本题的进阶方法是使用迭代法。递归法本质上是依靠栈来实现,现在要用迭代法来模拟递归也要使用栈。核心逻辑为循环判断栈是否为空,不为空就将当前栈顶元素弹出栈。之后判断栈顶元素的左右子节点是否为空,若不为空就先弹入右节点、再弹入左节点,原因是栈遵循"先进后出",前序遍历时需要先遍历左节点再遍历右节点,所以让右节点先进去。需要注意的是,要考虑root节点为空的特殊情况,此时就需要直接返回。

3.基于以上思想,可写出完整代码如下:

cpp 复制代码
 1. /**
 2.  * Definition for a binary tree node.
 3.  * struct TreeNode {
 4.  *     int val;
 5.  *     struct TreeNode *left;
 6.  *     struct TreeNode *right;
 7.  * };
 8.  */
 9. /**
10.  * Note: The returned array must be malloced, assume caller calls free().
11.  */
12. // 二叉树前序遍历,迭代法(栈实现),顺序:根 -> 左 -> 右
13. int* preorderTraversal(struct TreeNode* root, int* returnSize) {
14.     // 分配结果数组,固定容量101
15.     int* res = (int*)malloc(sizeof(int) * 101);
16.     // cnt记录结果数组有效元素个数
17.     int cnt = 0;
18.     // 栈数组,存放树节点指针
19.     struct TreeNode* stack[101];
20.     // top为栈的下一个可写入位置
21.     int top = 0;
22.     // 根节点为空,直接返回空结果
23.     if (root == NULL) {
24.         *returnSize = 0;
25.         return res;
26.     }
27.     // 根节点先入栈
28.     stack[top++] = root;
29.     
30.     // 栈不为空就循环处理
31.     while (top != 0){
32.         // 弹出栈顶节点
33.         struct TreeNode* cur = stack[--top];
34.         // 访问当前节点,存入结果数组
35.         res[cnt++] = cur->val;
36.         // 先压右孩子(栈后进先出,右先入栈保证左先出栈)
37.         if (cur->right) stack[top++] = cur->right;
38.         // 再压左孩子
39.         if (cur->left) stack[top++] = cur->left;
40.     }
41.     // 设置返回数组有效长度
42.     *returnSize = cnt;
43.     return res;
44. }

该算法时间复杂度和空间复杂度均为O(n)。

相关推荐
金士曼1 小时前
从规则到涌现:算法认知的三个层次
算法
彧azz1 小时前
图的最短路径:Dijkstra与Floyd算法
数据结构·笔记·学习
人效思维笔记1 小时前
阿米巴推行前,经营者要先做好哪些准备?
经验分享·笔记·阿米巴·阿米巴经营·中国式阿米巴
AgentMaster2 小时前
数据资产化落地难题:5款数据中台系统架构对比与实施记录
大数据·人工智能·算法
志尊宝2 小时前
Vue3 零基础每日笔记(047):动态路由与路由参数——:id 传参、query 传参、props 解耦
前端·javascript·vue.js·笔记·html5
鹿角片ljp2 小时前
从 Kimi Cyber Reasoning 学习网络安全推理数据集:从 Reasoning SFT 到安全 Agent 数据设计
数据结构·算法
圣保罗的大教堂3 小时前
leetcode 3629. 通过质数传送到达终点的最少跳跃次数 中等
leetcode
圣保罗的大教堂3 小时前
leetcode 1914. 循环轮转矩阵 中等
leetcode
沪上企服通3 小时前
旧账系统的信创迁移工程:从 MySQL/Oracle 到国产库、国密与电子会计档案闭环
数据库·笔记·数据库架构