94.binary-tree-inorder-traversal.md 6.4 KB
Newer Older
Y
yulecc 已提交
1
## 题目地址(94. 二叉树的中序遍历)
L
lucifer 已提交
2

Y
yulecc 已提交
3
https://leetcode-cn.com/problems/binary-tree-inorder-traversal/
L
luzhipeng 已提交
4 5

## 题目描述
L
lucifer 已提交
6

L
luzhipeng 已提交
7
```
Y
yulecc 已提交
8
给定一个二叉树,返回它的中序 遍历。
L
luzhipeng 已提交
9

Y
yulecc 已提交
10
示例:
L
luzhipeng 已提交
11

Y
yulecc 已提交
12
输入: [1,null,2,3]
L
luzhipeng 已提交
13 14 15 16 17 18
   1
    \
     2
    /
   3

Y
yulecc 已提交
19 20 21
输出: [1,3,2]
进阶: 递归算法很简单,你可以通过迭代算法完成吗?

L
luzhipeng 已提交
22
```
L
lucifer 已提交
23 24 25 26 27 28

## 前置知识

- 二叉树
- 递归

29 30 31 32 33 34 35
## 公司

- 阿里
- 腾讯
- 百度
- 字节

L
luzhipeng 已提交
36 37 38 39 40 41 42 43 44 45 46 47 48 49
## 思路

递归的方式相对简单,非递归的方式借助栈这种数据结构实现起来会相对轻松。

如果采用非递归,可以用栈(Stack)的思路来处理问题。

中序遍历的顺序为左-根-右,具体算法为:

- 从根节点开始,先将根节点压入栈

- 然后再将其所有左子结点压入栈,取出栈顶节点,保存节点值

- 再将当前指针移到其右子节点上,若存在右子节点,则在下次循环时又可将其所有左子结点压入栈中, 重复上步骤

L
lucifer 已提交
50
![94.binary-tree-inorder-traversal](https://tva1.sinaimg.cn/large/007S8ZIlly1ghlu4qkvu0g30qp0eywoh.gif)
L
luzhipeng 已提交
51 52

(图片来自: https://github.com/MisterBooo/LeetCodeAnimation)
L
lucifer 已提交
53

L
luzhipeng 已提交
54 55 56
## 关键点解析

- 二叉树的基本操作(遍历)
L
lucifer 已提交
57
  > 不同的遍历算法差异还是蛮大的
L
luzhipeng 已提交
58 59 60 61 62 63
- 如果非递归的话利用栈来简化操作

- 如果数据规模不大的话,建议使用递归

- 递归的问题需要注意两点,一个是终止条件,一个如何缩小规模

L
lucifer 已提交
64
1. 终止条件,自然是当前这个元素是 null(链表也是一样)
L
luzhipeng 已提交
65 66

2. 由于二叉树本身就是一个递归结构, 每次处理一个子树其实就是缩小了规模,
L
lucifer 已提交
67 68
   难点在于如何合并结果,这里的合并结果其实就是`left.concat(mid).concat(right)`,
   mid 是一个具体的节点,left 和 right`递归求出即可`
L
luzhipeng 已提交
69 70 71

## 代码

L
lucifer 已提交
72
- 语言支持:JS,C++,Python3, Java
R
raof01 已提交
73 74 75

JavaScript Code:

L
luzhipeng 已提交
76 77 78 79 80
```js
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
L
lucifer 已提交
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
var inorderTraversal = function (root) {
  // 1. Recursive solution
  // if (!root) return [];
  // const left = root.left ? inorderTraversal(root.left) : [];
  // const right = root.right ? inorderTraversal(root.right) : [];
  // return left.concat([root.val]).concat(right);

  // 2. iterative solutuon
  if (!root) return [];
  const stack = [root];
  const ret = [];
  let left = root.left;

  let item = null; // stack 中弹出的当前项

  while (left) {
    stack.push(left);
    left = left.left;
  }

  while ((item = stack.pop())) {
    ret.push(item.val);
    let t = item.right;

    while (t) {
      stack.push(t);
      t = t.left;
L
luzhipeng 已提交
108
    }
L
lucifer 已提交
109
  }
L
luzhipeng 已提交
110

L
lucifer 已提交
111
  return ret;
L
luzhipeng 已提交
112 113
};
```
L
lucifer 已提交
114

R
raof01 已提交
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
C++ Code:

```c++
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<TreeNode*> s;
        vector<int> v;
        while (root != NULL || !s.empty()) {
            for (; root != NULL; root = root->left)
                s.push_back(root);
            v.push_back(s.back()->val);
            root = s.back()->right;
            s.pop_back();
        }
        return v;
    }
};
```
L
lucifer 已提交
143

144
Python Code:
L
lucifer 已提交
145

146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
```Python
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def inorderTraversal(self, root: TreeNode) -> List[int]:
        """
        1. 递归法可以一行代码完成,无需讨论;
        2. 迭代法一般需要通过一个栈保存节点顺序,我们这里直接使用列表
          - 首先,我要按照中序遍历的顺序存入栈,这边用的逆序,方便从尾部开始处理
          - 在存入栈时加入一个是否需要深化的参数
          - 在回头取值时,这个参数应该是否,即直接取值
          - 简单调整顺序,即可实现前序和后序遍历
        """
        # 递归法
        # if root is None:
        #     return []
        # return self.inorderTraversal(root.left)\
        #     + [root.val]\
        #     + self.inorderTraversal(root.right)
        # 迭代法
        result = []
        stack = [(1, root)]
        while stack:
            go_deeper, node = stack.pop()
            if node is None:
                continue
            if go_deeper:
                # 左右节点还需继续深化,并且入栈是先右后左
                stack.append((1, node.right))
                # 节点自身已遍历,回头可以直接取值
                stack.append((0, node))
                stack.append((1, node.left))
            else:
                result.append(node.val)
        return result
```
L
luzhipeng 已提交
187

188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
Java Code:

- recursion

```java
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    List<Integer> res = new LinkedList<>();
    public List<Integer> inorderTraversal(TreeNode root) {
        inorder(root);
        return res;
    }
L
lucifer 已提交
208

209 210
    public void inorder (TreeNode root) {
        if (root == null) return;
L
lucifer 已提交
211

212
        inorder(root.left);
L
lucifer 已提交
213

214
        res.add(root.val);
L
lucifer 已提交
215

216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
        inorder(root.right);
    }
}
```

- iteration

```java
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<> ();
        Stack<TreeNode> stack = new Stack<> ();

        while (root != null || !stack.isEmpty()) {
            while (root != null) {
                stack.push(root);
                root = root.left;
            }
            root = stack.pop();
            res.add(root.val);
            root = root.right;
        }
        return res;
    }
}
```
251 252 253 254

## 相关专题

- [二叉树的遍历](https://github.com/azl397985856/leetcode/blob/master/thinkings/binary-tree-traversal.md)
L
lucifer 已提交
255 256 257 258 259


大家对此有何看法,欢迎给我留言,我有时间都会一一查看回答。更多算法套路可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 37K star 啦。
大家也可以关注我的公众号《力扣加加》带你啃下算法这块硬骨头。
![](https://tva1.sinaimg.cn/large/007S8ZIlly1gfcuzagjalj30p00dwabs.jpg)