This commit is contained in:
krahets
2023-07-21 21:53:04 +08:00
parent 2338b35039
commit 175cf59c9d
18 changed files with 324 additions and 35 deletions

View File

@@ -13,12 +13,16 @@ status: new
<p align="center"> Fig. 构建二叉树的示例数据 </p>
### 判断是否为分治问题
原问题定义为从 `preorder``inorder` 构建二叉树。我们首先从分治的角度分析这道题:
- **问题可以被分解**:从分治的角度切入,我们可以将原问题划分为两个子问题:构建左子树、构建右子树,加上一步操作:初始化根节点。而对于每个子树(子问题),我们仍然可以复用以上划分方法,将其划分为更小的子树(子问题),直至达到最小子问题(空子树)时终止。
- **子问题是独立的**:左子树和右子树是相互独立的,它们之间没有交集。在构建左子树时,我们只需要关注中序遍历和前序遍历或后序遍历中与左子树对应的部分。右子树同理。
- **子问题的解可以合并**:一旦我们得到了左子树和右子树,我们可以将它们链接到根节点上,从而得到原问题的解。
### 如何划分子树
根据以上分析,这道题是可以使用分治来求解的,但问题是:**如何通过前序遍历 `preorder` 和中序遍历 `inorder` 来划分左子树和右子树呢**
根据定义,`preorder``inorder` 都可以被划分为三个部分:
@@ -36,6 +40,8 @@ status: new
<p align="center"> Fig. 在前序和中序遍历中划分子树 </p>
### 使用指针描述子树区间
至此,**我们已经推导出根节点、左子树、右子树在 `preorder``inorder` 中的索引区间**。而为了描述这些索引区间,我们需要借助几个指针变量:
- 将当前树的根节点在 `preorder` 中的索引记为 $i$
@@ -60,6 +66,8 @@ status: new
<p align="center"> Fig. 根节点和左右子树的索引区间表示 </p>
### 代码实现
接下来就可以实现代码了。为了提升查询 $m$ 的效率,我们借助一个哈希表 `hmap` 来存储 `inorder` 列表元素到索引的映射。
=== "Java"