从先序遍历还原二叉树
难度:
标签:
题目描述
我们从二叉树的根节点 root
开始进行深度优先搜索。
在遍历中的每个节点处,我们输出 D
条短划线(其中 D
是该节点的深度),然后输出该节点的值。(如果节点的深度为 D
,则其直接子节点的深度为 D + 1
。根节点的深度为 0
)。
如果节点只有一个子节点,那么保证该子节点为左子节点。
给出遍历输出 S
,还原树并返回其根节点 root
。
示例 1:
输入:"1-2--3--4-5--6--7" 输出:[1,2,5,3,4,6,7]
示例 2:
输入:"1-2--3---4-5--6---7" 输出:[1,2,5,3,null,6,null,4,null,7]
示例 3:
输入:"1-401--349---90--88" 输出:[1,401,null,349,88,90]
提示:
- 原始树中的节点数介于
1
和1000
之间。 - 每个节点的值介于
1
和10 ^ 9
之间。
代码结果
运行时间: 40 ms, 内存: 16.4 MB
/*
题目思路:
1. 使用Java流和分割字符串的方法来简化节点的识别和构建。
2. 将输入字符串分割成节点信息。
3. 使用栈来维护当前节点的层级关系,并根据深度信息插入到正确的位置。
*/
import java.util.*;
import java.util.stream.*;
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
public class Solution {
public TreeNode recoverFromPreorder(String S) {
List<String> nodes = Arrays.stream(S.split("(?<=\d)(?=-)|(?<=-)(?=\d)"))
.collect(Collectors.toList());
Deque<TreeNode> stack = new ArrayDeque<>();
for (String nodeInfo : nodes) {
int level = 0;
while (nodeInfo.charAt(level) == '-') level++;
int value = Integer.parseInt(nodeInfo.substring(level));
TreeNode node = new TreeNode(value);
while (stack.size() > level) {
stack.pop();
}
if (!stack.isEmpty()) {
if (stack.peek().left == null) {
stack.peek().left = node;
} else {
stack.peek().right = node;
}
}
stack.push(node);
}
while (stack.size() > 1) {
stack.pop();
}
return stack.pop();
}
}
解释
方法:
本题通过模拟树的深度优先搜索(DFS)的先序遍历来还原二叉树。首先解析输入的字符串,根据'-'的数量确定节点的深度,然后解析节点的数值。使用栈来存储已经解析的节点,并根据节点的深度调整栈的大小,以模拟回溯到正确的父节点。当解析到一个新节点时,根据其深度与栈顶节点的关系来确定它是左子节点还是右子节点。最后,栈底的节点是树的根节点。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
在处理字符串时,如何确保在遇到连续的'-'和数字时正确分离出每个节点的深度和值?
▷🦆
为什么在构建新节点后要将其添加到栈中,栈在这里扮演了什么角色?
▷🦆
当栈的长度大于当前节点的深度时,为什么要弹出栈顶元素?这与树的结构有什么关系?
▷🦆
如何处理一个节点只有左子节点而没有右子节点的情况,这在代码中是如何反映的?
▷