力扣算法题—094中序遍历二叉树【】

本文详细介绍了二叉树的中序遍历算法,包括递归和非递归(使用栈和Morris遍历)两种实现方式,提供了完整的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

给定一个二叉树,返回它的中序 遍历。

示例:

输入: [1,null,2,3]
   1
    \
     2
    /
   3

输出: [1,3,2]

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

 

 

 1 //递归遍历
 2 class Solution {
 3 public:
 4     vector<int> inorderTraversal(TreeNode* root) {
 5         vector<int>res;
 6         helper(res, root);
 7         return res;
 8     }
 9     void helper(vector<int>&res, TreeNode* root) {
10         if (root==NULL)
11             return;
12         if (root->left)
13             helper(res, root->left);
14         res.push_back(root->val);
15         if (root->right)
16             helper(res, root->right);
17     }
18 };
19 
20 
21 //非递归遍历
22 class Solution {
23 public:
24     vector<int> inorderTraversal(TreeNode* root) {
25         vector<int>res;
26         stack<TreeNode*>s;
27         TreeNode* p = root;
28         while (p || !s.empty()) {
29             while (p) {
30                 s.push(p);
31                 p = p->left;
32             }//找到最左节点
33             p = s.top();
34             s.pop();
35             res.push_back(p->val);
36             p = p->right;
37         }
38         return res;
39     }
40 };
41 
42 
43 //另一种解法
44 // Non-recursion and no stack
45 class Solution {
46 public:
47     vector<int> inorderTraversal(TreeNode *root) {
48         vector<int> res;
49         if (!root) return res;
50         TreeNode *cur, *pre;
51         cur = root;
52         while (cur) {
53             if (!cur->left) {
54                 res.push_back(cur->val);
55                 cur = cur->right;
56             }
57             else {
58                 pre = cur->left;
59                 while (pre->right && pre->right != cur) pre = pre->right;
60                 if (!pre->right) {
61                     pre->right = cur;
62                     cur = cur->left;
63                 }
64                 else {
65                     pre->right = NULL;
66                     res.push_back(cur->val);
67                     cur = cur->right;
68                 }
69             }
70         }
71         return res;
72     }
73 };

 

转载于:https://www.cnblogs.com/zzw1024/p/10787632.html

### 力扣二叉树序遍历的Java实现思路 #### 方法一:递归解法 递归是一种直观且易于理解的方法。通过定义一个辅助函数 `dfs`,按照 **左子树 -> 根节点 -> 右子树** 的顺序依次处理每个节点。对于每一个节点,如果它不为空,则先递归遍历其左子树,接着将该节点的值加入结果列表,最后递归遍历右子树。 以下是具体的代码实现: ```java class Solution { public List<Integer> inorderTraversal(TreeNode root) { List<Integer> res = new ArrayList<>(); dfs(res, root); return res; } private void dfs(List<Integer> res, TreeNode node) { if (node == null) { return; } dfs(res, node.left); // 递归遍历左子树 res.add(node.val); // 访问根节点 dfs(res, node.right); // 递归遍历右子树 } } ``` 这种方法的时间复杂度和空间复杂度均为 O(n),其中 n 是二叉树中的节点数[^3]。 --- #### 方法二:迭代解法 迭代方法的核心思想是手动模拟递归过程中使用的栈结构。由于递归本质上也是利用系统栈完成操作,因此可以通过显式的栈来替代系统的隐式调用栈。 具体步骤如下: 1. 初始化一个空的结果列表 `res` 和一个栈 `stack`。 2. 使用一个指针变量 `current` 指向当前正在访问的节点。 3. 当前节点不为空或栈不为空时进入循环: - 如果当前节点存在,将其压入栈并继续移动到它的左子节点; - 否则弹出栈顶元素(即最近一次未完全访问的节点),记录其值,并转向其右子节点。 4. 循环结束后返回结果列表。 下面是对应的代码实现: ```java class Solution { public List<Integer> inorderTraversal(TreeNode root) { List<Integer> res = new ArrayList<>(); Deque<TreeNode> stack = new LinkedList<>(); TreeNode current = root; while (current != null || !stack.isEmpty()) { while (current != null) { // 将所有左子节点压入栈 stack.push(current); current = current.left; } current = stack.pop(); // 弹出栈顶元素 res.add(current.val); // 添加到结果集 current = current.right; // 移动至右子节点 } return res; } } ``` 此方法同样具备时间复杂度 O(n)[^2] 和最坏情况下空间复杂度也为 O(n) 的特性。 --- #### 方法三:Morris 遍历 Morris 遍历是一种不需要额外存储空间的高效算法,其核心思想是在遍历时修改树的结构以建立临时链接,从而避免使用栈或递归来保存中间状态。最终恢复原始树形结构的同时完成了遍历。 主要逻辑分为以下几个部分: 1. 初始设置当前节点为根节点。 2. 对于每个节点,判断是否有左子树: - 若无左子树,则直接访问该节点并将指针移向右子树; - 若有左子树,则找到左子树中最右侧的节点(即前驱节点)并当前节点连接起来;随后再次调整指针位置。 3. 继续上述过程直至整棵树被完整遍历完毕。 以下是 Morris 遍历的具体实现: ```java class Solution { public List<Integer> inorderTraversal(TreeNode root) { List<Integer> res = new ArrayList<>(); TreeNode current = root; while (current != null) { if (current.left == null) { // 左子树不存在 res.add(current.val); // 直接访问当前节点 current = current.right; // 转移到右子树 } else { // 存在左子树 TreeNode predecessor = findPredecessor(current); if (predecessor.right == null) { // 前驱尚未连接回当前节点 predecessor.right = current; // 创建反向链路 current = current.left; // 进入左子树 } else { // 前驱已连接回来 predecessor.right = null; // 断开反向链路 res.add(current.val); // 访问当前节点 current = current.right; // 转移到右子树 } } } return res; } private TreeNode findPredecessor(TreeNode node) { TreeNode pred = node.left; while (pred.right != null && pred.right != node) { pred = pred.right; } return pred; } } ``` 这种做法的空间复杂度仅为 O(1)[^4],因为除了输入数据外无需任何附加内存支持。 --- ### 总结 以上介绍了三种不同的 Java 实现方案用于解决力扣上的二叉树序遍历问题。每种方法各有优劣,在实际应用中可以根据需求灵活选用合适的策略。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值