您的位置:首页 > 其它

每日打卡:从先序遍历还原二叉树

2020-07-18 04:22 447 查看

打卡: 从先序遍历还原二叉树

心情

《隐秘的角落》电视剧拍得太真实了,每个人都背负着枷锁走在这个世界上。有些时候看着自己的内心,就像是看着一个不相干的人在做着另一个世界的事情。

读题

leetcode: 1028. 从先序遍历还原二叉树

描述:
我们从二叉树的根节点 root 开始进行深度优先搜索。
在遍历中的每个节点处,我们输出 D 条短划线(其中 D 是该节点的深度),然后输出该节点的值。(如果节点的深度为 D,则其直接子节点的深度为 D + 1。根节点的深度为 0)。
如果节点只有一个子节点,那么保证该子节点为左子节点。
给出遍历输出 S,还原树并返回其根节点 root。

测试用例:
输入:“1-2–3--4-5–6--7”
输出:[1,2,5,3,4,6,7]
输入:“1-2–3—4-5–6—7”
输出:[1,2,5,3,null,6,null,4,null,7]
输入:“1-401–349—90–88”
输出:[1,401,null,349,88,90]

提示:
原始树中的节点数介于 1 和 1000 之间。
每个节点的值介于 1 和 10 ^ 9 之间。

先序遍历,二叉树,好熟悉~

思路

1:递归吧

实现

class Solution {
public TreeNode recoverFromPreorder(String S) {
TreeNode node = null;
if (S != null && S.length() > 0) {
String num = getNumber(S,"-");
node = new TreeNode(Integer.valueOf(num));
parseNode(node, S.substring(num.length()), "-");
}
return node;
}

/**
* 字符串转换为树
* @param node 当前节点
* @param str  左侧树
* @param trim 分割的字符串
* @return
*/
public String parseNode(TreeNode node, String str, String trim) {
if (str.length() > 0) {
String resultStr = trimStr(str, trim);
//strs[0]必然为空,不为空也不需要处理
//左侧树
if (str.length() - resultStr.length() == trim.length()) {
String num = getNumber(resultStr,"-");
node.left = new TreeNode(Integer.valueOf(num));
if (resultStr.length() > num.length()) {
str = parseNode(node.left, resultStr.substring(num.length()), trim + "-");
}else{
str = resultStr;
}
}
//右侧树
resultStr = trimStr(str, trim);
if (str.length() - resultStr.length() == trim.length()) {
String num = getNumber(resultStr,"-");
node.right = new TreeNode(Integer.valueOf(num));
if (resultStr.length() > num.length()) {
str = parseNode(node.right, resultStr.substring(num.length()), trim + "-");
}else{
str = resultStr;
}
}
}
return str;
}

/**
* 移除字符串前面的指定字符串
* @param str
* @param prefix
* @return
*/
public String trimStr(String str, String prefix) {
if (str.length() > 0 && str.startsWith(prefix)) {
return trimStr(str.substring(prefix.length()), prefix);
} else {
return str;
}
}

/**
* 获取字符串最前面的数值
* @param str
* @param prefix
* @return
*/
public String getNumber(String str, String prefix) {
if(str.indexOf(prefix)!=-1){
str = str.substring(0,str.indexOf(prefix));
}
return str;
}
}

还是比较清晰的思路,依次处理左节点再处理右节点。

提交


本想着用-分割子集,然后递归分割就能实现结果。结果卡在了第一步,用-分割子集要循环太多次……

标答

class Solution {
public TreeNode recoverFromPreorder(String S) {
// 存储当前节点的路径
Deque<TreeNode> path = new LinkedList<TreeNode>();
// 存储字符串中的位置
int pos = 0;
while (pos < S.length()) {
// 获取当前层数
int level = 0;
while (S.charAt(pos) == '-') {
++level;
++pos;
}
// 获取节点值
int value = 0;
while (pos < S.length() && Character.isDigit(S.charAt(pos))) {
value = value * 10 + (S.charAt(pos) - '0');
++pos;
}
// 构造当前节点
TreeNode node = new TreeNode(value);
if (level == path.size()) {
//如果当前节点的深度==当前路径长度(前一个节点是当前节点的父节点)
if (!path.isEmpty()) {
//如果不是第一个节点,前一个节点的左子节点为当前节点
path.peek().left = node;
}
}else {
//如果当前节点的深度!=当前路径长度(前一个节点不是当前节点的父节点)
while (level != path.size()) {
//通过queue弹出其他子节点,找到当前节点的父节点
path.pop();
}
// 找到父节点,因为此时左子节点已确定,所以赋值给右子节点
path.peek().right = node;
}
// 放入queue中
path.push(node);
}
// 全部弹出,只剩根节点
while (path.size() > 1) {
path.pop();
}
// 返回根
return path.peek();
}
}

官方题解

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: