|
| 1 | +--- |
| 2 | +title: 94.二叉树的中序遍历 |
| 3 | +date: 2024-02-10 11:37:39 |
| 4 | +tags: [题解, LeetCode, 简单, 栈, 树, 深度优先搜索, DFS, 二叉树, 递归] |
| 5 | +--- |
| 6 | + |
| 7 | +# 【LetMeFly】94.二叉树的中序遍历:递归/迭代(栈模拟递归) |
| 8 | + |
| 9 | +力扣题目链接:[https://leetcode.cn/problems/binary-tree-inorder-traversal/](https://leetcode.cn/problems/binary-tree-inorder-traversal/) |
| 10 | + |
| 11 | +<p>给定一个二叉树的根节点 <code>root</code> ,返回 <em>它的 <strong>中序</strong> 遍历</em> 。</p> |
| 12 | + |
| 13 | +<p> </p> |
| 14 | + |
| 15 | +<p><strong>示例 1:</strong></p> |
| 16 | +<img alt="" src="https://assets.leetcode.com/uploads/2020/09/15/inorder_1.jpg" style="height: 200px; width: 125px;" /> |
| 17 | +<pre> |
| 18 | +<strong>输入:</strong>root = [1,null,2,3] |
| 19 | +<strong>输出:</strong>[1,3,2] |
| 20 | +</pre> |
| 21 | + |
| 22 | +<p><strong>示例 2:</strong></p> |
| 23 | + |
| 24 | +<pre> |
| 25 | +<strong>输入:</strong>root = [] |
| 26 | +<strong>输出:</strong>[] |
| 27 | +</pre> |
| 28 | + |
| 29 | +<p><strong>示例 3:</strong></p> |
| 30 | + |
| 31 | +<pre> |
| 32 | +<strong>输入:</strong>root = [1] |
| 33 | +<strong>输出:</strong>[1] |
| 34 | +</pre> |
| 35 | + |
| 36 | +<p> </p> |
| 37 | + |
| 38 | +<p><strong>提示:</strong></p> |
| 39 | + |
| 40 | +<ul> |
| 41 | + <li>树中节点数目在范围 <code>[0, 100]</code> 内</li> |
| 42 | + <li><code>-100 <= Node.val <= 100</code></li> |
| 43 | +</ul> |
| 44 | + |
| 45 | +<p> </p> |
| 46 | + |
| 47 | +<p><strong>进阶:</strong> 递归算法很简单,你可以通过迭代算法完成吗?</p> |
| 48 | + |
| 49 | + |
| 50 | + |
| 51 | +## 方法一:深度优先搜索DFS(递归) |
| 52 | + |
| 53 | +写一个函数进行深搜: |
| 54 | + |
| 55 | +函数接受一个节点作为参数,若节点为空则直接返回,否则递归左子节点,当前节点加入答案,递归右子节点。 |
| 56 | + |
| 57 | +从根节点开始使用上述函数递归,递归完成后返回答案。 |
| 58 | + |
| 59 | ++ 时间复杂度$O(size(tree))$ |
| 60 | ++ 空间复杂度$O(size(tree))$ |
| 61 | + |
| 62 | +### AC代码 |
| 63 | + |
| 64 | +#### C++ |
| 65 | + |
| 66 | +```cpp |
| 67 | +class Solution { |
| 68 | +private: |
| 69 | + vector<int> ans; |
| 70 | + |
| 71 | + void dfs(TreeNode* root) { |
| 72 | + if (!root) { |
| 73 | + return ; |
| 74 | + } |
| 75 | + dfs(root->left); |
| 76 | + ans.push_back(root->val); |
| 77 | + dfs(root->right); |
| 78 | + } |
| 79 | +public: |
| 80 | + vector<int> inorderTraversal(TreeNode* root) { |
| 81 | + dfs(root); |
| 82 | + return ans; |
| 83 | + } |
| 84 | +}; |
| 85 | +``` |
| 86 | +
|
| 87 | +#### Python |
| 88 | +
|
| 89 | +```python |
| 90 | +# from typing import Optional, List |
| 91 | +
|
| 92 | +# # Definition for a binary tree node. |
| 93 | +# class TreeNode: |
| 94 | +# def __init__(self, val=0, left=None, right=None): |
| 95 | +# self.val = val |
| 96 | +# self.left = left |
| 97 | +# self.right = right |
| 98 | +
|
| 99 | +class Solution: |
| 100 | + def dfs(self, root: Optional[TreeNode]) -> None: |
| 101 | + if not root: |
| 102 | + return |
| 103 | + self.dfs(root.left) |
| 104 | + self.ans.append(root.val) |
| 105 | + self.dfs(root.right) |
| 106 | +
|
| 107 | + def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]: |
| 108 | + self.ans = [] |
| 109 | + self.dfs(root) |
| 110 | + return self.ans |
| 111 | +``` |
| 112 | + |
| 113 | +## 方法二:使用栈模拟递归(栈模拟递归) |
| 114 | + |
| 115 | +递归过程中实际上是系统使用栈帮你存下了当前的信息,调用函数结束后恢复当前信息继续往下执行。因此我们使用栈模拟一下递归即可。 |
| 116 | + |
| 117 | +递归的时候都需要保存哪些信息呢?其实我们只需要保存```当前节点是什么```和```当前节点是否递归过(左)子节点```即可。 |
| 118 | + |
| 119 | +若是*第一次处理到这个节点*,则先将右子入栈,再将本节点再次入栈(并标记一下说左子节点入过栈了),最后将左子节点入栈。(这样出栈顺序将时左中右) |
| 120 | + |
| 121 | +出栈时先看节点是否为空,为空直接返回。若左子节点入栈过了,则将当前节点值加入答案;否则(左子还未入栈),执行“第一次处理到这个节点”的操作。 |
| 122 | + |
| 123 | ++ 时间复杂度$O(size(tree))$ |
| 124 | ++ 空间复杂度$O(size(tree))$ |
| 125 | + |
| 126 | +使用栈模拟递归,时空复杂度都不变,但毕竟保存的信息变少了,将会更高效。 |
| 127 | + |
| 128 | +### AC代码 |
| 129 | + |
| 130 | +#### C++ |
| 131 | + |
| 132 | +```cpp |
| 133 | +class Solution { |
| 134 | +public: |
| 135 | + vector<int> inorderTraversal(TreeNode* root) { |
| 136 | + vector<int> ans; |
| 137 | + stack<pair<TreeNode*, bool>> st; // [<node, ifPushedChild>, ... |
| 138 | + st.push({root, false}); |
| 139 | + while (st.size()) { |
| 140 | + auto [thisNode, ifPushedChild] = st.top(); |
| 141 | + st.pop(); |
| 142 | + if (!thisNode) { |
| 143 | + continue; |
| 144 | + } |
| 145 | + if (ifPushedChild) { |
| 146 | + ans.push_back(thisNode->val); |
| 147 | + } |
| 148 | + else { |
| 149 | + st.push({thisNode->right, false}); |
| 150 | + st.push({thisNode, true}); |
| 151 | + st.push({thisNode->left, false}); |
| 152 | + } |
| 153 | + } |
| 154 | + return ans; |
| 155 | + } |
| 156 | +}; |
| 157 | +``` |
| 158 | +
|
| 159 | +#### Python |
| 160 | +
|
| 161 | +```python |
| 162 | +# from typing import Optional, List |
| 163 | +
|
| 164 | +# # Definition for a binary tree node. |
| 165 | +# class TreeNode: |
| 166 | +# def __init__(self, val=0, left=None, right=None): |
| 167 | +# self.val = val |
| 168 | +# self.left = left |
| 169 | +# self.right = right |
| 170 | +
|
| 171 | +class Solution: |
| 172 | + def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]: |
| 173 | + ans = [] |
| 174 | + st = [(root, False)] |
| 175 | + while st: |
| 176 | + thisNode, ifPushedChild = st.pop() |
| 177 | + if not thisNode: |
| 178 | + continue |
| 179 | + if ifPushedChild: |
| 180 | + ans.append(thisNode.val) |
| 181 | + else: |
| 182 | + st.append((thisNode.right, False)) |
| 183 | + st.append((thisNode, True)) |
| 184 | + st.append((thisNode.left, False)) |
| 185 | + return ans |
| 186 | +
|
| 187 | +``` |
| 188 | + |
| 189 | +> 同步发文于CSDN,原创不易,转载经作者同意后请附上[原文链接](https://blog.tisfy.eu.org/2024/02/10/LeetCode%200094.%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E4%B8%AD%E5%BA%8F%E9%81%8D%E5%8E%86/)哦~ |
| 190 | +> Tisfy:[https://letmefly.blog.csdn.net/article/details/136090242](https://letmefly.blog.csdn.net/article/details/136090242) |
0 commit comments